先看代码:
package cn.itcast.algorithm.demo.three; /** * @author :caizhengjie * @description : * @date :2021/7/23 18:51 */ public class TestThread { public static void main(String[] args) { // 面试题:线程的run方法和start方法的区别 Runnable task = new Runnable() { @Override public void run() { System.out.println("run() --- " + Thread.currentThread().getName()); } }; Thread t1 = new Thread(task,"t1"); t1.run(); t1.start(); } }
运行结果:
run() --- main run() --- t1
我们可以发现run方法和start方法运行出来的结果不一样,start才是真正启动t1线程的,调用start方法之后,run方法是由t1线程执行的
原理解释:
t1.run():通过run方法启动线程其实就是调用一个类中的方法,当作普通方法的方式调用。并没有创建一个线程,程序中依旧只有一个主线程,必须等到run()方法里面的代码执行完毕,才会继续执行下面的代码,这样就没有达到多线程的目的。
t1.start():则表示,重新开启一个线程,不必等待其他线程运行完,只要得到cup就可以运行该线程。只有通过调用线程类的start()方法才能真正达到多线程的目的。
源码解读:
可以看到,当一个线程启动的时候,它的状态(threadStatus)被设置为0(即线程为NEW状态),如果不为0,则抛出IllegalThreadStateException异常。正常的话,将该线程加入线程组,最后尝试调用start0方法,而start0方法是私有的native方法(Native Method是一个java调用非java代码的接口)。
start调用后,线程出于就绪状态RUNNABLE而非运行状态,等分配到cpu时间片时系统会调用thread的run()方法,而这个方法其实只是调用runnable里面自己实现的run()方法。当run()方法结束后,此线程就会终止。(start之后就绪,start调用run才运行)
再看run方法源码:
如果target不为空,则调用target的run()方法。target其实就是一个实现Runnable接口的对象实例,正如上面代码中new Thread的部分,其实我们就是在实现它的run()方法。所以如果直接调用run,就和调用实例的一个普通方法没什么区别,是不会创建新的线程的,因为压根就没执行start0方法。