线程的生命周期
一、线程的生命周期
线程一个完整的生命周期要经历如下五种状态:
- 新建:当一个Thread类或者其子类的对象被声明并创建时,新生的线程对象处于新建状态
- 就绪:处于新建状态的西纳城被start()之后,将进入线程队列等待CPU时间片
- 运行:当就绪的线程被调度并会的处理器资源时,便进入运行状态,run()方法定义了线程的操作和功能
- 阻塞:在某种特殊情况下,被人为挂起挥着执行输入输出操作时,让出CPU并临时中止自己的执行,进入阻塞状态
- 死亡:线程完成了它的全部工作或者线程被提前强制性的中止
二、线程的生命周期状态转换图
三、start方法源码分析
上面的API文档是说,当我们调用线程的start方法时,JVM会调用当前线程的run()方法。这样就同时有两个线程在运行(当前线程和调用线程start()方法的线程)
此外,同一个线程不能调用start()方法两次,否则会报错,IllegalThreadStateException
。
(1)线程调用两次start()方法测试
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
System.out.println("hello");
});
thread.start();
thread.start();
}
输出结果:
(2)start()内部源码分析
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
//状态校验 0:NEW 新建状态
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
group.add(this); // 添加进线程组
boolean started = false;
try {
start0(); //调用native方法执行线程run方法
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this); //启动失败,从线程组中移除当前前程。
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
四、Thread的run()与start()的区别?
调用start()后,线程会被放到等待队列,等待CPU调度,并不一定要马上开始执行,只是将这个线程置于可动行状态。然后通过JVM,线程Thread会调用run()方法,执行本线程的线程体。先调用start后调用run,这么麻烦,为了不直接调用run?就是为了实现多线程的优点,没这个start不行。
- start()方法来启动线程,真正实现了多线程运行。这时无需等待run方法体代码执行完毕,可以直接继续执行下面的代码;通过调用Thread类的start()方法来启动一个线程, 这时此线程是处于就绪状态, 并没有运行。 然后通过此Thread类调用方法run()来完成其运行操作的, 这里方法run()称为线程体,它包含了要执行的这个线程的内容, Run方法运行结束, 此线程终止。然后CPU再调度其它线程。
- run()方法当作普通方法的方式调用。程序还是要顺序执行,要等待run方法体执行完毕后,才可继续执行下面的代码; 程序中只有主线程——这一个线程, 其程序执行路径还是只有一条, 这样就没有达到写线程的目的。
记住:多线程就是分时利用CPU,宏观上让所有线程一起执行 ,也叫并发。