线程从创建并启动到消亡共经历了5种状态:新建(创建)、就绪、运行、阻塞和死亡
线程变化的5种状态转换:
-
新建状态(New):新创建了一个线程对象,但还没有启动。new Thread()
-
就绪状态(Runnable):线程已经创建并且已经完成了所有必要的准备工作,只等CPU的分配以开始执行。
线程对象创建后,其它线程调用了该对象的start()方法。只能针对处于新建状态的线程对象调用start方法,否则IllegalThreadStateException。
-
执行状态(Running):就绪状态的线程获取了CPU,执行程序代码run()。注意在一个多处理器的机器上会有多个线程并行执行。现在大部分桌面和服务器操作系统都采用时间片轮转法的抢占式调度策略,在选择下一个执行线程时系统会考虑线程的优先级。调用yield()方法可以让运行状态的线程转入就绪,可以避免出现某个线程长期占有CPU的问题
-
堵塞状态(Blocked):堵塞状态是线程由于某种原因(如等待I/O操作完成、等待获取锁等)放弃CPU使用权。临时停止执行。原因消失后线程进入就绪状态,才有机会转到执行状态。线程切换是由底层平台控制的,具有一定的随机性
-
死亡状态(Dead):线程运行完了或者因异常退出了run()方法,该线程结束生命周期。
直接调用该线程的stop方法也可以结束线程,但是这个方法容易导致数据不一致的问题,通常不推荐使用
当主线程结束时,其它线程不受任何影响,并不会随之结束,一旦子线程启动后则拥有和主线程相同的地位,并不受主线程的影响
IllegalThreadStateException是非法线程状态异常,该异常通常与线程的生命周期和状态管理有关
IllegalThreadStateException可能会在以下情况抛出:
当一个线程试图多次启动(调用
start()
方法)时,因为它只能被启动一次。一旦线程开始执行,它就不能再次回到“新建”状态。当一个线程试图在不适当的状态下调用某些方法时,例如在一个已经启动的线程上调用
start()
方法,或者在一个已经终止的线程上调用某些只能由活动线程调用的方法。在守护线程(Daemon Thread)的生命周期管理中,如果尝试在线程启动后更改其守护状态(通过调用
setDaemon(true)
),也可能抛出这个异常。这是因为在 Java 中,必须在线程启动之前设置其守护状态。
堵塞的情况分三种:
等待堵塞:执行的线程执行wait()方法,JVM会把该线程放入等待池中。
同步堵塞:执行的线程在获取对象的同步锁时,若该同步锁被别的线程占用。则JVM会把该线程放入锁池中。
其它堵塞:执行的 线程执行sleep()或join()方法,或者发出了I/O请求时。JVM会把该线程置为堵塞状态。当sleep()状态超时、join()等待 线程终止或者超时、或者I/O处理完成时。线程又一次转入就绪状态。