操作系统与Java中线程状态的区分

这篇博客详细介绍了操作系统中的3种或5种线程状态,并深入剖析了Java中的6种线程状态,包括NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING和TERMINATED。解释了各种状态的含义以及线程如何在这些状态之间进行切换,如从BLOCKED进入RUNNABLE,从WAITING进入RUNNABLE,以及从TIMED_WAITING进入RUNNABLE的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

操作系统中的3种or5种线程状态

3种

  1. 就绪
  2. 运行
  3. 阻塞
    在这里插入图片描述

5种

在这里插入图片描述

Java中的6种线程状态

6个状态

java.lang.Thread类内部维护了一个枚举类State,包含了Java线程的6种状态

public enum State {
	//新建
    NEW,
	//运行
    RUNNABLE,
    //阻塞
    BLOCKED,
    //等待
    WAITING,
	//超时等待
    TIMED_WAITING,
	//终止
    TERMINATED;
}

在这里插入图片描述

其中的RUNNABLE包括了运行状态就绪状态

NEW 新建

new Thread()创建了一个线程,还没有执行start()方法。此时线程状态是NEW

RUNNABLE 运行

调用的start(),这个线程会执行它的run()方法,此时进入RUNNABLW状态

  • RUNNABLE 对应了操作系统中线程状态的 Running 和 Ready
    也就是Runnable状态的线程可能正在运行,也可能处于就绪状态
  • 一个正在运行的线程ThreadA,它的状态是Runnable,如果任务没执行完,CPU时间片用完了,调度其他线程,ThreadA的状态还是Runnable,处于就绪态,随时可能被再次执行。

BLOCKED 阻塞

在进入synchronized代码块/方法 时,如果线程没有获取到对应的monitor锁,就会从Runnable运行状态进入Blocked阻塞状态

WAITING 等待

只有通过synchronized会进入阻塞Blocked
对于其他锁(ReentrantLock等),如果线程没有获取到锁,会直接进入Waiting状态
本质就是执行了LockSupport.park()方法进入Waiting状态

wait()/join()也会进入等待

BLOCKED阻塞状态 与 WAITING等待状态的区别

  • Blocked:没有获取到monitor锁,进入阻塞,等待其他线程释放monitor锁
  • Waiting:等待某个条件,调用了notify()/notifyAll(),或者join的线程执行完

TIMED_WAITING 超时等待

线程会进入超时等待的条件:执行以下带时间参数的方法时

方法方法签名所属类
wait(long timeout)public final native void wait(long timeout)Object
sleep(long millis)public static native void sleep(long millis)Thread
join(long millis)public final synchronized void join(long millis)Thread
parkNanos(Object blocker, long nanos)public static void parkNanos(Object blocker, long nanos)LockSupport
parkUntil(Object blocker, long deadline)public static void parkUntil(Object blocker, long deadline)LockSupport

LockSupport的park和unpark方法都是调用Unsafe类的本地方法
在这里插入图片描述

TERMINATED 终止

  1. run()方法执行完,线程结束
  2. 程序出现异常,意外终止了run()方法

线程状态的切换

从 Blocked 进入 Runnable 状态

Runnable进入Blocked是因为没有获得锁才进入了阻塞;
所以被阻塞的线程获得其他线程释放的monitor锁后,才可以从Blocked到Runnable

从 Waiting 进入 Runnable状态

  1. 执行LockSupport.unpark()
  2. join的线程结束
  3. 被中断
  • 如果通过其他线程调用notify()或 notifyAll()来唤醒它,那么它会直接进入Blocked 状态这里需要注意一点,因为唤醒 waiting线程的线程如果调用notify/notifyAll,要求必须先持有该 monitor锁,也就是wait、notify、notifyAll 必须在synchronized 代码块中。

  • 所以处于 waiting 状态的线程被唤醒时拿不到该锁,就会进入 Blocked 状态,直到执行了notify/notifyAll 唤醒它的线程执行完并且释放了 monitor锁,才可能轮到它去尝试获取这把锁,如果它得到了锁,就会从Blocked 状态进入Runnable状态。

从 TIMED_WAITING进入 Runnable状态

  1. 通过notify/notifyAll先进入阻塞Blocked,获取到锁后,再进入Runnable状态
  2. 超过设置的等待时间后,就会自动获取锁,直接进入Runnable
    join线程执行完 / LockSupport.unpark() / 被中断 都会直接进入Runnable不会经历Blocked阻塞
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值