在线程的生命周期中,要经过创建(new)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)5种状态。
当程序中多条线程启动后,CPU就会在多条线程之间切换运行,于是线程状态也会多次在运行、阻塞之间切换。
新建和就绪状态:
当程序使用new关键字创建了一个线程后,该线程就处于新建状态,此时它和其他的Java对象一样,仅仅由虚拟机为其分配内存,并初始化其成员变量的值。程序也还没开始执行线程体。
当线程对象调用start()方法后,该线程就处于就绪状态,虚拟机会为其创建方法调用栈和程序计数器,此时表示该线程可以运行了,是否开始运行何时开始运行取决与JVM里线程调度器的调度。
注意:线程应该调用start()方法来启动,如果直接调用线程对象的run()方法,则run()方法会立即被执行,而且在run()方法返回之前其他线程无法并发地执行,即系统把线程对象当成一个普通对象,而run()方法也是一个普通方法。
运行状态和阻塞状态:
如果处于就绪状态的线程获得了CPU,开始执行run()方法的线程执行体,该线程就处于运行状态。
线程进入阻塞状态的情况:
1.线程调用了sleep()方法主动发起占用的处理器资源。
2.线程调用了一个阻塞式IO方法,在该方法返回之前,该线程被阻塞。
3.线程试图获得一个同步监视器,但该同步监视器正被其他线程所持有。
4.线程在等待某个通知(notify)。
5.程序调用了线程的suspend()方法将该线程挂起。这个方法容易导致死锁。
线程被阻塞之后,其他线程就会获得执行的机会。被阻塞的线程会在合适的时候重新进入就绪状态,等待线程调度器调度。
如下情况下可以解除线程的阻塞:
1.调用sleep()方法的线程过了指定时间。
2.线程调用的阻塞式IO方法已经返回。
3.线程成功地获得了试图取得的同步监视器。
4.线程正在等待某个通知时,其他线程发出了一个通知。
5.处于挂起状态的线程被调用了resume()回复方法。
线程死亡:线程会以3中方式结束,结束后就处于死亡状态
1.run()或call()方法执行结束,线程正常结束
2.线程抛出一个未捕获的Exception或Error
3.直接调用该线程的stop()方法来结束该线程,该方法容易导致死锁。
线程对象的isAlive()方法在线程处于就绪、运行、阻塞状态时返回true,在线程处于新建、死亡状态时返回false。
程序只能对处于新建状态的线程调用start()方法启动线程。