一、线程生命周期的五种状态
线程从创建、运行到结束总是处于下面五个状态之一:新建状态、就绪状态、运行状态、阻塞状态及死亡状态。
新建状态(New):新创建了一个线程对象,Java虚拟机为其分配内存。
就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。就绪状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
运行状态(Running):就绪状态的线程获取了CPU,执行run()方法中的程序代码。
阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
等待阻塞(WAITING):运行的线程执行wait()方法,JVM会把该线程放入等待池中。
同步阻塞(Blocked):运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
超时阻塞(TIME_WAITING):运行的线程执行sleep(long)或join(long)方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。
死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
二、线程状态转换
首先,线程对象创建后,虚拟机只是为其分配内存,进入新建状态,线程对象与其他对象的创建相同,并不会表现出线程对象的特征。当线程对象的start()方法调用后,线程进入就绪状态,Java虚拟机会为其创建方法调用栈和程序计数器,处于就绪状态的线程并没有开始运行,只是表示该线程最好了准备,可以运行了,运行的时机取决于JVM里线程调度器的调度。
之后,如果处于就绪状态的线程获得了CPU,线程进入运行状态,开始执行run()方法的线程执行体,这个过程是由系统调度的,开发者无法控制。线程的执行过程中可能会被中断,目的是使其他线程获得执行的机会,正在运行的线程也可以调用线程控制方法放弃所占用的资源,线程进入阻塞状态,并在合适时候进入就绪状态。
最后,处于运行状态的线程会以下列三种方式结束,进入死亡状态。
- run()方法或者call()方法执行结束,线程正常结束。
- 线程抛出未捕获的异常。
- 调用线程的stop()方法结束该线程。