Java线程状态和状态切换
背景
先来探讨一个关于多线程的基础知识:java线程有多少种状态?根据JDK定义,答案是六种!为什么很多人给出的答案却是五种呢?这极有可能是将操作系统层面的线程状态和Java线程状态混为一谈了。因此,小编在翻阅JDK源码的基础上,介绍一下java线程的六种状态以及操作系统层面的五种状态,欢迎拍砖。
java线程状态
JDK中声明了六种Java线程状态,以枚举类的形式定义在Thread.State中,而且注释开篇撇清了和操作系统层面线程状态的关系——【这些状态是虚拟机状态,不反映任何操作系统的线程状态】,英文原文描述如下:
/**
* A thread can be in only one state at a given point in time.
* These states are virtual machine states which do not reflect
* any operating system thread states.
*
* @since 1.5
* @see #getState
*/
public class Thread implements Runnable {
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
}
简单来介绍一下这6种状态。
1))NEW:新建状态,新创建一个线程对象时的初始状态,此时尚未调用 start() 方法。
2)RUNNABLE:就绪状态,JAVA 线程把操作系统中的就绪和运行两种状态统一称为“就绪状态或者可运行状态”。英文相关描述如下:
A thread in the runnable state is executing in the Java virtual machine but it may be waiting for other resources from the operating system such as processor.
线程对象创建后,其它线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu的使用权。
3)BLOCKED:阻塞状态,表示线程进入等待状态,也就是线程因为某种原因放弃了 CPU 使用权,阻塞也分为几种情况 :
等待阻塞:运行的线程执行了 Thread.sleep 、Object.wait()、 join() 等方法,JVM 会把当前线程设置为等待状态,当 sleep 结束、join 线程终止或者线程被唤醒后,该线程从等待状态进入到阻塞状态,重新抢占锁后进行线程恢复。
同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被其它线程锁占用了,那么JVM会把当前的线程放入到锁池中。
其他阻塞:发出了 I/O请求时,JVM 会把当前线程设置为阻塞状态,当 I/O处理完毕则线程恢复。
4)WAITING:等待状态,没有超时时间,要被其它线程或者有其它的中断操作;即一个正在无限期等待另一个线程执行一个特别的动作的线程处于WAITING状态,英文原文如下:
A thread that is waiting indefinitely for another thread to perform a particular action is in this state.
一个线程进入 WAITING 状态是因为调用了方法Object.wait(), Thread.join()或者LockSupport.park()。然后会等其它线程执行一个特别的动作,比如:
- 一个调用了Thread.join方法的线程会等待指定的线程结束。
- 一个调用了某个对象的wait方法的线程会等待另一个线程调用此对象的notify() 或 notifyAll()。
5)TIMED_WAITING:超时等待状态,超时以后自动返回;如下方法执行超时,就会进入超时等待状态:Thread.sleep(long)、Object.wait(long)、Thread.jjoin(long)、LockSupport.park(long)、LockSupport.parkNanos(long)、LockSupport.parkUntil(long)。
6)TERMINATED:终止状态,表示当前线程执行完毕 。
我们可以通过函数getState()来查看线程的当前状态:
/**
* Returns the state of this thread.
* This method is designed for use in monitoring of the system state,
* not for synchronization control.
*
* @return this thread's state.
* @since 1.5
*/
public State getState() {
// get current thread state
return jdk.internal.misc.VM.toThreadState(threadStatus);
}
线程状态间的转换
借一个图来描述:

关于具体的转换场景,图中描述的比较清楚,此处不再赘述。注意:
1)sleep、join、yield时并不释放对象锁资源,而执行函数wait()时会释放锁,对象在被notify/notifyAll唤醒时,重新去抢夺获取对象锁资源。
2)sleep可以在任何地方使用,而wait,notify,notifyAll只能在同步方法或者同步块中使用。
3)调用obj.wait()会立即释放锁,以便其他线程可以执行notify(),但是notify()不会立刻立刻释放sycronized(obj)中的对象锁,必须要等notify()所在线程执行完同步方法或者同步块才会释放这把锁,然后供线程等待池的线程来抢夺对象锁。
wait方法是Object的方法,线程释放锁,进入WAITING或TIMED_WAITING状态。等待时间到了或被notify/notifyAll唤醒后,回去竞争锁,如果获得锁,进入RUNNABLE,否则进入阻塞状态等待获取锁。
操作系统层面线程状态
很多人会把操作系统层面的线程状态与java线程状态混淆,所以导致有的文章中把java线程状态写成是5种,在此我们说清楚一个问题,java线程状态是6个,操作系统层面的线程状态是5种,如下图所示:

下面分别介绍一下这5种状态:
1)new :一个新的线程被创建,等待该线程被调用执行。
2)ready :表示线程已经被创建,正在等待系统调度分配CPU使用权或者时间片已用完,此线程被强制暂停,等待下一个属于它的时间片到来。
3)running :表示线程获得了CPU使用权,正在占用时间片。
4)waiting :表示线程等待(或者说挂起),等待某一事件(如IO或另一个线程)执行完,让出CPU资源给其他线程使用。
5)terminated :一个线程完成任务或者其它终止条件发生,该线程终止进入退出状态,退出状态释放该线程所分配的资源。
需要注意的是,操作系统中的线程除去new 和terminated 状态,一个线程真实存在的状态是ready 、running和waiting 。
Thread.State 中的RUNNABLE 状态涵盖了 操作系统层面的【可运行状态】、【运行状态】和【阻塞状态】(由于 BIO 导致的线程阻塞,在 Java 里无法区分,仍然认为是可运行,就好比我们在run()方法里调用IO方法,再者虽然有线程上下文切换但在JAVA层面还是运行的)。
小结
关于Java线程池状态及其切换,各位同仁可以参考《Java线程池状态和状态切换》。
至此,我们就把java线程状态以及操作系统层面的线程状态厘清了,是不是以后再也不会混淆了?希望能帮助到大家。
Reference
Java线程状态和状态切换的更多相关文章
- Java线程Thread的状态解析以及状态转换分析 多线程中篇(七)
线程与操作系统中线程(进程)的概念同根同源,尽管千差万别. 操作系统中有状态以及状态的切换,Java线程中照样也有. State 在Thread类中有内部类 枚举State,用于抽象描述Java线程的 ...
- java线程五种状态
java线程五种状态: 创建 -> 就绪 -> 运行 -> 销毁 创建 -> 就绪 -> 运行 -> 等待(缺少资源) -> 销毁 下图:各种状态转换
- 为什么 Java 线程没有 Running 状态?
Java虚拟机层面所暴露给我们的状态,与操作系统底层的线程状态是两个不同层面的事.具体而言,这里说的 Java 线程状态均来自于 Thread 类下的 State 这一内部枚举类中所定义的状态: 什么 ...
- java线程的五大状态,阻塞状态详解
一.状态简介 一个线程的生命周期里有五大状态,分别是: 新生 就绪 运行 死亡 运行后可能遇到的阻塞状态 二.相关方法 2.1 新生状态 Thread t = new Thread(); 正如我们前面 ...
- java线程四种状态
一个线程可以有四种状态: 1.新(new), 即线程刚刚创建,而并未执行 2.可运行(runnable),意味着一旦时间分片机制有空闲的CPU周期提供给一个线程,那个线程便可立即开始运行.因此,线程可 ...
- Java线程的六种状态
java线程有很多种状态,最主要的有六种,被创建.运行.睡眠.等待.阻塞以及消亡六种,也有很多归结为5种,把睡眠以及等待归结为冻结: 被创建:就是线程被创建,就是new thread()之后就是创建一 ...
- JAVA线程间的状态转换
线程间的状态转换: 1. 新建(new):新创建了一个线程对象. 2. 可运行(runnable):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法.该状态的线程位于可运 ...
- Java-技术专区-如何监控Java线程池的状态
线程池介绍 什么是线程池.线程池核心类.线程池工作流程.线程池分类.拒绝策略.及如何提交与关闭线程池等. 但在实际开发过程中,在线程池使用过程中可能会遇到各方面的故障,如线程池阻塞,无法提交新任务等. ...
- java线程控制、状态同步、volatile、Thread.interupt以及ConcurrentLinkedQueue
在有些严格的系统中,我们需要做到干净的停止线程并清理相关状态.涉及到这个主题会带出很多的相关点,简单的总结如下: 我们知道,在java中,有一个volatile关键字,其官方说明(https://do ...
- Java线程状态及切换
Java线程状态及切换 一.什么是Java线程状态 在Java程序中,用于描述Java线程的六种状态: 新建(NEW):当前线程,刚刚新建出来,尚未启动. 运行(RUNNABLE):当前线程,处于竞争 ...
随机推荐
- 别再混淆了!JVM内存模型和Java内存模型的本质区别
JVM 内存模型(JVM Memory Model)和 Java 内存模型(Java Memory Model, JMM)是 Java 开发中两个非常重要的概念,但这两个概念很容易被搞混,所以本文就来 ...
- C# Semaphore
1.Semaphore定义Semaphore,是负责协调各个线程, 以保证它们能够正确.合理的使用公共资源.也是操作系统中用于控制进程同步互斥的量. Semaphore常用的方法有两个WaitOne( ...
- pip 提示import error,cannot import name locations
出现这个问题的原因: 环境中没有安装年文件 安装了,环境路径错误 解决如下: 首先 执行升级命令 升级到最新 python -m pip install -U pip 再到site-packages目 ...
- Redis 是什么?
Redis 的定义? 百度百科: Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.K ...
- 【Spring】事务操作
事务概念 1.什么事务 事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个失败所有操作都失败 典型场景:银行转账 lucy 转账 100 元 给 mary lucy 少 100,mar ...
- [T.4] 团队项目:团队代码管理准备
团队的代码仓库地址 [GitHub - Meng-XuanYu/JayJay-TeamVersionControl: A public repo for BUAASE2025 course homew ...
- Wolfram常用计算
1.方程与方程组 例1:求解方程 参考表达式: solve x^3 + 2x^2 - 6x + 5 = 0 real 求解所有根 例2:求解方程: 参考表达式: solve ax^2+bx+c=0 注 ...
- 康谋方案 | 从概念到生产的自动驾驶软件在环(SiL)测试解决方案
一.自动驾驶软件在环(SiL)测试解决方案 自动驾驶软件在环(SiL)测试解决方案能够研究和验证高历程实验和恶劣驾驶环境下的AD系统的性能,支持云端和PC端操作,提供高保真度的仿真环境和传感器模型,实 ...
- MySQL 中的 Log Buffer 是什么?它有什么作用?
MySQL 中的 Log Buffer 是什么?它有什么作用? Log Buffer 是 MySQL InnoDB 存储引擎的一部分,用于存储写入日志数据的内存区域.它主要用于记录事务的变更日志,这些 ...
- Golang 版本导致的容器运行时问题
问题现场 用户反馈安装了某个 containerd 版本的节点无法正常拉起容器,业务场景是在 K8S Pod 里面运行一个 Docker,在容器里面通过 docker 命令再启动新的容器. 报错信息如 ...