线程的生命周期
当线程被创建并启动以后,它既不是一启动就进入执行状态,也不是一直处于执行状态,在线程的生命周期中,他要经过新建(new),就绪(Runnable),运行(Running),阻塞(Blocked),死亡(Dead)5种状态。尤其是当线程启动以后,他不可能一直占有CPU独自云溪,所以CPU需要在多个线程之间切换,于是线程状态也会多次在运行,就绪之间切换。
新建状态和就绪状态:
- 当程序使用new关键字创建一个线程之后,该线程就处于新建状态;此时他和其他java对象一样,没有任何区别;
- 当线程调用start()方法后,线程进入就绪状态,java虚拟机会为其创建方法调用栈和程序计数器,处于此状态的线程并没有开始运行,只是表示该线程可以运行了。至于该线程何时开始运行,取决于JVM里线程调度器的调度。
运行和阻塞状态:
- 如果处于就绪状态的线程获得了CPU,开始执行run()方法的线程执行体,则该线程处于运行状态,如果计算机只有一个CPU,那么在任何时刻只有一个线程处于运行状态。
- 当发生如下情况时,线程将会进入阻塞状态:
a,线程调用sleep()方法主动放弃所占用的处理器资源;
b,线程调用了一个阻塞式IO方法,在该方法返回之前,该线程被阻塞;
c,线程在等待某个通知(notify);
d,程序调用了线程的suspend()方法将线程挂起。 - 如下情况会使线程由阻塞状态变为就绪状态:
a,调用sleep()方法的线程经过了指定时间;
b,线程调用的阻塞式IO方法已经返回;
c,线程正在等待某个通知时,其他线程发出了一个通知;
d,处于挂起状态的线程被调用了resume()恢复方法。
线程状态转换图如下:
从图中可以看出:阻塞状态只能进入就绪状态,无法直接进入运行状态;当处于运行状态的线程失去CPU时或调用了yield()方法会进入就绪状态。
线程死亡:
线程会以3种方式进入死亡状态:
- run()或call()方法执行完成,线程正常结束;
- 线程抛出一个未捕获的Exception或Error;
- 直接调用线程的stop()方法结束该线程。
可以调用isAlive()方法测试线程是否死亡:当线程处于就绪,运行,阻塞时,该方法返回true;当线程处于新建,死亡时,返回false。
代码演示:
package com.dalingjia.thead;
public class StartDead extends Thread{
private int i ;
public void run(){
for ( ; i < 100 ; i++) {
System.out.println(getName()+"\t"+ i);
}
}
public static void main(String[] args) {
StartDead sDead = new StartDead();
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+"\t"+i);
if (i==20) {
sDead.start();
//测试线程是否处于活动状态
System.out.println(sDead.isAlive());
}
//线程结束,线程死亡,想要再次启动线程就必须新建线程
if (i>20 && !sDead.isAlive()) {
sDead.start();
}
}
}
}
注意:不要试图对一个已经死亡的线程调用start()方法使它重新启动,死亡就是死亡,该线程将不可再次作为线程执行,必须再次新建一个线程。