Java线程的6种状态
介绍Java线程的运行状态之前,我们先来看下1.5版本后的JDK Thread类中定义的State枚举类:
public enum State {
/**
* Thread state for a thread which has not yet started.
*/
NEW,
/**
* Thread state for a runnable thread.
*/
RUNNABLE,
/**
* Thread state for a thread blocked waiting for a monitor lock.
*
*/
BLOCKED,
/**
* Thread state for a waiting thread.
*/
WAITING,
/**
* Thread state for a waiting thread with a specified waiting time.
*/
TIMED_WAITING,
/**
* Thread state for a terminated thread.
*/
TERMINATED;
}
由此我们可以知道,在java中线程状态一共有6种,分别是:New(新建)、Runnable(运行)、Blocked(阻塞)、Waitting(无限期等待)、Timed Watting(限期等待)、Terminated(终止),下面我们来对这些状态逐一分析。(备注:中文状态名词翻译参考周志明的《深入理解 Java 虚拟机》)
新建(NEW)
Thread state for a thread which has not yet started.
新创建了一个线程对象,但是还没有开始执行,可以理解为还没有调用start()方法。Java中线程运行启动是需要调用start()方法,再会执行native start0方法,实际上会调用到JVM_StartThread方法,而JVM_StartThread最终才会调用Java当前线程类中的run方法,相关代码可以看在jvm.cpp文件。
Java线程中的run()方法只是一个类中的普通方法,如果直接调用依然是主线程来执行程序,会顺序的同步执行,达不到多线程的效果。
运行(Runnable)
Thread state for a runnable thread.
运行(Runnable)状态包含了线程的就绪(Ready)和运行中(Runing)状态,因为当调用start()方法后,新的线程是先是就绪状态,因为要等待操作系统CPU的调度,当CPU时间片分配到了才是运行中状态。
- 就绪(Ready)
线程对象被创建后,创先线程调用了该new线程的start()方法。 - 运行中(Runing)
就绪状态的线程被操作系统调度后,获得了CPU的时间片,进行运行中状态。
阻塞(Blocked)
Thread state for a thread blocked waiting for a monitor lock.
这个状态通常发生在有一个线程锁住了要执行的对象,比如在使用synchronized、lock的时候。
无限期等待(Waitting)
Thread state for a waiting thread.
这种状态通常是被没有加入时间的睡眠等待,如:
- Object.wait()
- Thread.sleep(0)
- Thread.join()
- LockSupport.park()
加了这些条件时,线程无法被CPU分配时间片,也一直处于等待中,直到一定条件才能被唤醒,如显示的调用notify(),notifyAll(),LockSupport.unpark()。
限期等待(Timed Watting)
Thread state for a waiting thread with a specified waiting time.
这样状态的线程是被加了一定时间的等待,在等待一定时间后自动唤醒,CPU就会分配时间片,就绪状态变成运行。通常发生在下面代码中:
- Thread.sleep()
- 设置了 Timeout 参数的 Object.wait()
- 设置了 Timeout 参数的 Thread.join()
- LockSupport.parkNanos()方法
- LockSupport.parkUnit()方法
终止(Terminated)
Thread state for a terminated thread.
线程已经终止运行,包括线程已经完成任务,也可能是被interrupted。
状态之间转换
参考国外的一张图,对于线程的生命周期描绘的很具体,Runable状态是OS在参与调度。