这是从 操作系统
【初始状态】仅是在语言层面创建了线程对象,还未与操作系统线程关联
【可运行状态】(就绪状态)指该线程已经被创建(与操作系统线程关联),可以由 CPU 调度执行
【运行状态】指获取了 CPU 时间片运行中的状态
当 CPU 时间片用完,会从【运行状态】转换至【可运行状态】,会导致线程的上下文切换
【阻塞状态】
如果调用了阻塞 API,如 BIO 读写文件,这时该线程实际不会用到 CPU,会导致线程上下文切换,进入【阻塞状态】
等 BIO 操作完毕,会由操作系统唤醒阻塞的线程,转换至【可运行状态】
与【可运行状态】的区别是,对【阻塞状态】的线程来说只要它们一直不唤醒,调度器就一直不会考虑调度它们
【终止状态】表示线程已经执行完毕,生命周期已经结束,不会再转换为其它状态
这是从 Java API 层面来描述的,根据 Thread.State 枚举,分为六种状态
NEW
线程刚被创建,但是还没有调用 start()
方法
RUNNABLE
(RUNNING)当调用了 start()
方法之后,注意,Java API 层面的 RUNNABLE
状态涵盖了 操作系统 层面的【可运行状态】、【运行状态】和【阻塞状态】(由于 BIO 导致的线程阻塞,在 Java 里无法区分,仍然认为是可运行)
BLOCKED
,WAITING
,TIMED_WAITING
都是 Java API 层面对【阻塞状态】的细分,后面会在状态转换一节详述
TERMINATED
当线程代码运行结束
代码示例
@Slf4j(topic = "c.TestState") public class TestState { public static void main(String[] args) throws IOException { Thread t1 = new Thread("t1") { @Override public void run() { log.debug("running..."); } }; // 未start 所以日志未打印 Thread t2 = new Thread("t2") { @Override public void run() { while(true) { // runnable } } }; t2.start(); Thread t3 = new Thread("t3") { @Override public void run() { log.debug("running..."); } }; t3.start(); Thread t4 = new Thread("t4") { @Override public void run() { synchronized (TestState.class) { try { Thread.sleep(1000000); // timed_waiting } catch (InterruptedException e) { e.printStackTrace(); } } } }; t4.start(); Thread t5 = new Thread("t5") { @Override public void run() { try { t2.join(); // waiting } catch (InterruptedException e) { e.printStackTrace(); } } }; t5.start(); Thread t6 = new Thread("t6") { @Override public void run() { synchronized (TestState.class) { // blocked try { Thread.sleep(1000000); } catch (InterruptedException e) { e.printStackTrace(); } } } }; t6.start(); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } log.debug("t1 state {}", t1.getState()); log.debug("t2 state {}", t2.getState()); log.debug("t3 state {}", t3.getState()); log.debug("t4 state {}", t4.getState()); log.debug("t5 state {}", t5.getState()); log.debug("t6 state {}", t6.getState()); System.in.read(); } }
输出