1、Thread的.start()与.run()的区别
start()
start()方法启动线程,真正实现了多线程运行,无需等待方法体代码执行完毕就可以直接继续执行下面的代码。
严格来说,start()后线程进入就绪状态(ready),进入可运行线程池;之后获得CPU时间成为了运行中状态(running)。
java中将就绪和运行中状态统称为运行(RUNNABLE)。
run()
run()方法将线程体当作普通方法的方式调用,程序依然是要顺序执行。
run方法体执行完毕后才可继续执行下面的代码(实际上程序中依然只有主线程这一个线程)。
2、试验1
public class Try {
public static void main(String... args) {
Runnable runTask = () -> {
try {
System.out.println("sleeping...");
Thread.sleep(5000);
System.out.println("awake");
} catch (InterruptedException e) {
System.out.println("睡觉时被打");
}
};
Thread thread1 = new Thread(runTask);
Thread thread2 = new Thread(runTask);
Thread thread3 = new Thread(runTask);
thread1.start();
thread2.start();
thread3.start();
}
}
运行结果:
sleeping...
sleeping...
sleeping...
awake
awake
awake
可以看到使用start()方法时三个线程一起启动,睡5秒后一起结束。
将最后的执行部分替换成run(),再来看一下结果
thread1.run();
thread2.run();
thread3.run();
运行结果:
sleeping...
awake
sleeping...
awake
sleeping...
awake
三个线程按顺序先后执行,总计耗时15s
3、试验2
这个例子是为了说明,start启动的线程,确确实实是线程自己在跑,跟main()已经没关系了。
public class Try {
public static void main(String... args) throws InterruptedException {
Runnable runTask = () -> {
try {
System.out.println(Thread.currentThread().getName()
+ " - " + Thread.currentThread().getState());
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("睡觉时被打");
}
};
Thread thread = new Thread(runTask);
thread.setName("小张");
System.out.println(thread.getName() + " - " + thread.getState());
thread.start();
// 这是为了确保线程真的跑完,查看到正确的状态
Thread.sleep(2000);
System.out.println(thread.getName() + " - " + thread.getState());
}
}
运行结果:
小张 - NEW
小张 - RUNNABLE
小张 - TERMINATED
-
new Thread()以后,打印出线程处于初始状态(NEW)
(实现Runnable接口或者继承Thread可以得到一个线程类,new一个实例出来,线程就进入了初始状态)
-
start()方法使线程变为运行状态(RUNNABLE)
-
等待2秒后,线程确实结束,此时状态为终止(TERMINATED)
接下来仍然将start()替换为run()看一下结果:
Thread thread = new Thread(runTask);
thread.setName("小张");
System.out.println(thread.getName() + " - " + thread.getState());
thread.run();
// 这是为了确保线程真的跑完,查看到正确的状态
Thread.sleep(2000);
System.out.println(thread.getName() + " - " + thread.getState());
运行结果:
小张 - NEW
main - RUNNABLE
小张 - NEW
-
new Thread()以后,小张处于初始状态(NEW)
-
run()方法被调用后,实际的处理是main()线程自己跑的,main变成了运行状态(RUNNABLE)——即使调用的语句是thread.run(),而不是诸如main.run()
-
main将调用部分运行完毕以后,小张仍然处于初始状态(NEW),没有任何变化
4、稍微深入一点来分析这件事情
Thread类中,start()方法调用的是一个native方法start0(),启动一个线程,最终在线程里执行目标对象的run()方法;
而直接使用run()方法的话,我们来看一下run()的代码:
@Override
public void run() {
if (target != null) {
target.run();
}
}
其中的target,是在new Thread(runTask)时,通过构造器传入的,就是runTask这个实例自身。
所以直接调用线程的run方法,就相当于调用普通方法一样,由上往下执行。
网友评论