# 简述

操作系统中的线程和编程语言中的线程是一一对应的, 在这篇文章中, 我要让自己彻底弄懂线程.

# 操作系统的线程生命周期

要想弄懂线程, 首先得清楚它是一个什么概念, 可以去Wikipedia上了解, 其次你需要线程的生命周期, 对它有个宏观上的了解.

每种编程语言对操作系统的线程都进行了不同程度的封装(可能是组合, 也可能是细分), 所以我们有必要来先了解下操作系统的线程生命周期.

下图为操作系统的生命周期:

操作系统的线程生命周期

# 状态是如何转换的

# 1. NEW

此状态一般被称为"新建", 属于编程语言层面的状态, 不是由操作系统实现.

在Java中继承Thread或实现Runnable就可以创建一个NEW状态线程, 注意此时没有调用start()哦.

# 2. NEW -> RUNNABLE

线程在操作系统中被创建, 等待CPU的调度.

在Java中对创建后的线程调用start(), 其状态即由NEW变为RUNNABLE, 等待时间片的分配.

# 3. RUNNABLE -> RUNNING

CPU分配了时间片给线程, 则线程状态变为RUNNING

Java中统一为RUNNABLE

# 4. RUNNING -> SLEEP

当运行中的线程调用某个阻塞API等待某个事件时, 线程状态变为SLEEP(休眠状态), 释放CPU时间片, SLEEP状态的线程永远没有机会获得CPU时间片. 当等待事件结束或者阻塞API调用结束, 线程由SLEEP状态再变为RUNNABLE.

# 5. RUNNING -> TERMINATED

线程执行完或者发生异常就会变成TERMINATED状态, 此状态的线程不会再有状态变更了, 同时也表示线程的生命周期结束了.

# Java线程的生命周期

上面说完操作系统的生命周期, 下面来聊聊正题, 那Java线程的生命周期是什么样的?

下图为Java线程的生命周期:

Java线程的生命周期

# 状态之间如何转换

# 1. NEW

Java有两种创建线程的方式

  1. 继承Thread类
  2. 实现Runnable接口

创建线程之后, 此线程就处于NEW状态, 这是属于编程语言层面的状态

# 2. NEW -> RUNNABLE

对创建的线程类调用start(), 即将线程状态由NEW变为RUNNABLE

# 3. RUNNABLE -> BLOCKED

线程等待synchronized的隐式锁时, 等待线程会从RUNNABLE变为BLOCKED

# 4. RUNNABLE -> WAITING

三种场景会触发此状态变换:

  1. 调用Object.wait();
  2. 调用Thread.join();
  3. 调用LockSupport.park();
# 5. RUNNABLE ->TIMED_WAITING

五种场景会触发此状态变换:

  1. 调用Thread.sleep(long l);
  2. 调用Object.wait(long l);
  3. 调用Thread.join(long l);
  4. 调用LockSupport.parkNanos(Object blocker, long l);
  5. 调用LockSupport.parkUntil(long l);
# 6. RUNNABLE -> TERMINATED

两种常见场景:

  1. 线程执行完
  2. 发生异常

使用stop()已经不推荐了, 正确停止线程请使用interrupt()

# Java为什么没有RUNNING状态

Java将RUNNABLE和RUNNING统一归为RUNNABLE状态

# 阻塞式API或等I/O时为什么不是BLOCKED状态

进行这两类操作时, 操作系统会将线程由RUNNING变为SLEEP, 但是在JVM中都统一归为RUNNABLE状态.

修改于: 8/11/2022, 3:17:56 PM