一、概念
Thread实现了Runnable接口
1 public class Thread implements Runnable {
2 /* Make sure registerNatives is the first thing <clinit> does. */
3 private static native void registerNatives();
4 static {
5 registerNatives();
6 }
7
8 private volatile char name[];
9 //表示线程的优先级(最大值为10,最小值为1,默认值为5),
10 private int priority;
11
12
13 /* Whether or not the thread is a daemon thread. */
14 //表示线程是否是守护线程,如果在main线程中创建了一个守护线程,
15 //当main方法运行完毕之后,守护线程也会随着消亡。在JVM中,垃圾收集器线程就是守护线程。
16 private boolean daemon = false;
17
18
19 /* What will be run. */
20 //表示要执行的任务。
21 private Runnable target;
22 。。。。。。
23 }
二、创建,启动线程的方法有两种:
1,继承Thread
1 class PrimeThread extends Thread {
2 long minPrime;
3 PrimeThread(long minPrime) {
4 this.minPrime = minPrime;
5 }
6
7 public void run() {
8 // compute primes larger than minPrime
9 . . .
10 }
11 }
12
13 PrimeThread p = new PrimeThread(143);
14 p.start();
2,实现Runnable
1 class PrimeRun implements Runnable {
2 long minPrime;
3 PrimeRun(long minPrime) {
4 this.minPrime = minPrime;
5 }
6
7 public void run() {
8 // compute primes larger than minPrime
9 . . .
10 }
11 }
12
13
14 PrimeRun p = new PrimeRun(143);
15 new Thread(p).start();
3,分析
但都调用thread的start()启动线程,API的注解是:
Causes this thread to begin execution; the Java Virtual Machine calls the <code>run</code> method of this thread.(使该线程开始执行;Java 虚拟机调用该线程的 run 方法。)
用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法,这里方法 run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。
而thread的run()方法只是一个普通方法而已,API的注解是:
If this thread was constructed using a separate <code>Runnable</code> run object, then that <code>Runnable</code> object's <code>run</code> method is called;otherwise, this method does nothing and returns.(如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。)
如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。
1 public class ThreadTest extends Thread{
2
3 @Override
4 public void run() {
5 System.out.println("Thread Start !");
6 }
7
8 public static void main(String[] args) {
9 ThreadTest threadTest = new ThreadTest();
10 threadTest.start();
11 System.out.println("不用等待!");
12 }
13 }
结果:
1 不用等待! 2 Thread Start !
1 public class ThreadTest extends Thread{
2
3 @Override
4 public void run() {
5 System.out.println("Thread Start !");
6 }
7
8 public static void main(String[] args) {
9 ThreadTest threadTest = new ThreadTest();
10 threadTest.run();
11 System.out.println("不用等待!");
12 }
13 }
结果:
1 Thread Start ! 2 不用等待!
参考博文链接: https://www.cnblogs.com/renhui/p/6066750.html
三、关于卖票的问题:
1,extends Thread
1 public class MyThread extends Thread {
2 private int tickets = 10;
3 @Override
4 public void run() {
5
6 for (int i = 0; i <= 100; i++) {
7 if(tickets>0){
8 System.out.println(Thread.currentThread().getName()+"--卖出票:" + tickets--);
9 }
10 }
11 }
12 public static void main(String[] args) {
13 MyThread thread1 = new MyThread();
14 MyThread thread2 = new MyThread();
15 MyThread thread3 = new MyThread();
16
17 thread1.start();
18 thread2.start();
19 thread3.start();
20 }
21 }
结果:
1 Thread-0--卖出票:10 2 Thread-2--卖出票:10 3 Thread-2--卖出票:9 4 Thread-2--卖出票:8 5 Thread-2--卖出票:7 6 Thread-2--卖出票:6 7 Thread-1--卖出票:10 8 Thread-1--卖出票:9 9 Thread-2--卖出票:5 10 Thread-0--卖出票:9 11 Thread-0--卖出票:8 12 Thread-0--卖出票:7 13 Thread-0--卖出票:6 14 Thread-0--卖出票:5 15 Thread-0--卖出票:4 16 Thread-0--卖出票:3 17 Thread-0--卖出票:2 18 Thread-0--卖出票:1 19 Thread-2--卖出票:4 20 Thread-1--卖出票:8 21 Thread-2--卖出票:3 22 Thread-1--卖出票:7 23 Thread-2--卖出票:2 24 Thread-1--卖出票:6 25 Thread-2--卖出票:1 26 Thread-1--卖出票:5 27 Thread-1--卖出票:4 28 Thread-1--卖出票:3 29 Thread-1--卖出票:2 30 Thread-1--卖出票:1
问题:每个线程都独立,不共享资源,每个线程都卖出了10张票,总共卖出了30张。
2,implements Runnable
1 public class MyRunnable implements Runnable {
2
3 private int tickets = 64100;
4 @Override
5 public void run() {
6 for (int i = 0; i <= 64200; i++) {
7 if(tickets>0){
8 System.out.println(Thread.currentThread().getName()+"--卖出票:"+ tickets-- );
9 }
10 }
11 }
12
13 public static void main(String[] args) {
14 MyRunnable myRunnable = new MyRunnable();
15 Thread thread1 = new Thread(myRunnable, "窗口一");
16 Thread thread2 = new Thread(myRunnable, "窗口二");
17 Thread thread3 = new Thread(myRunnable, "窗口三");
18
19 thread1.start();
20 thread2.start();
21 thread3.start();
22 }
23 }
问题:每个线程共享了对象myRunnable的资源,但是当tickets足够大的时候就会出现一张票被卖出去多次的问题,原因是:读取共享变量tickets和减一这两个动作是原子操作,但这两个动作不可能用一条指令完成,一旦在这两个动作之间发生线程的切换,同一个值就会被读取2次,从而发生错误!
解决方案就是在方法上加锁:
1 synchronized (this) {
2 if (tickets > 0) {
3 System.out.println(Thread.currentThread().getName() + "--卖出票:" + tickets--);
4 }
5 }
四、拓展
关于Thread的详细源码剖析可参考:https://www.cnblogs.com/dennyzhangdd/p/7280032.html
关于Thread多次start一个线程报错:IllegalThreadStateException()
----------------------------------------------多做多解决多总结-----------------------------------
来源:https://www.cnblogs.com/sqy123/p/9780110.html