线程的状态转换
线程生命周期的六种状态
-
New (新建)
-
Running (可运行)
-
Blocked (被阻塞)
-
Waiting (等待)
-
Timed Waiting (计时等待)
-
Terminated (被终止)
在我们程序编码中如果想要却动线程当前的状态,可以通过getState()方法来获取,同时我们需要注意任何线程在任何时刻都只能是处于一种状态
New 新建状态
首先我们展示一下整个线程状态的转换流程图,下面将进行详细的介绍讲解,如图所示,我们可以直观的看到六种状态的转换,首先左侧上方是NEW 状态,这是创建新线程的状态,相当于我们new Thread()的过程。
New 表示线程被创建但尚未启动的状态:当我们 new Thread() 新建一个线程实例时,如果线程没有开始运行start() 方法,那么线程也就没有开始执行 run()方法里面的代码,那么此时它的状态为 NEW。
而一旦线程调用了start(),它的状态就会从New —> Runnable(可运行状态)
Runnable 可运行状态
-
Java 中的Runnable 状态对应操作线程状态的两种状态,分别是Ready【就绪状态】和Running【执行状态】
Java 中处于 Runnable 状态的线程有可能正在执行,也有可能没有正在执行,正在等待被分配CPU时间片
-
所以,如果一个正在运行的线程是 Runnable 状态,当它运行到一半任务时,执行该线程的 CPU时间片被占用,
导致该线程暂时不运行,它的状态依然不变,还是Runnable,因为它有可能随时被调度回来继续执行任务
Blocked 被阻塞状态
- 首先我们来认识一下Blocked状态,这是一个相对简单的状态,我们可以通过下面图示看到,从Runable 状态进入Blocked状态只有一种途径,那么就是当进入到synchronized 代码中时未获得monitor锁(synchronized 是基于monitor锁实现的)
Waiting 等待状态
对于waiting 状态的进入有三种情况分别为:
- 当线程中调用了没有设置 Timeout 参数的 object.wait() 方法
- 当线程中调用了没有设置 Timeout 参数的 Thread.join() 方法
- 当线程调用了 LockSupport.part() 方法
关于LockSupport.part() 方法,这里说一下,我们通过上面知道Blocked是针对synchronized 的monitor所得,但是Java中实际是有很多其他锁的,比如ReetranrLock等,在这些锁中,如果线程没有获取到锁则会直接进入waiting状态,其实这种本质上它就是执行了LockSupport.part() 方法进入了waiting状态
-
Blocked 与Waiting 的区别
Blocked 是在等待其他线程释放 monitor锁
Waiting 则是在等待某个条件,比如join的线程执行完毕,或者notify()或notifyAll()
Timed Waiting 计时等待状态
最后说一下Time waiting状态,它与waiting状态非常相似,其中的区别只在于是否有时间的限制,Time waiting状态时会等待超时,之后由系统唤醒,或者也可以提前被通知;如:notify()或notifyAll()
在一下情况会让线程进入Time waiting状态
- 线程执行了设置时间参数的 Thread.sleep(long millis) 方法
- 线程执行了设置时间参数的 object.wait(long timeout) 方法
- 线程执行了设置时间参数的 Thread.join(long millis) 方法
- 线程执行了设置时间参数的 LockSupport.parknanos(long millis) 方法和LockSupport.partuntil(long dealine) 方法
Terminated 终止状态
线程执行完任务或者发生异常导致线程终止时进入终止状态
线程的状态流转过程图:
场景1:当线程处于Running 状态时,调用了Thread.sleep(参数)方法时,则线程进入Time Waiting(计时等待)状态,若sleep(参数)时间到,则又重新进入Running (可运行)状态
场景2:当线程处于Running 状态时,获得到锁之后并调用了object.wait(参数)方法时,则线程进入Time Waiting(计时等待)状态
如果wait时间到,并获取到锁,则线程重新进入Running(可运行)状态
如果wait时间到,没有获取到锁,则线程进入Blocked(阻塞)状态
如果wait时间未到,其它线程调用了object.notify()或object.notifyAll() 方法,该线程被被动唤醒并获取到锁,则线程重新进入Running(可运行)状态
如果wait时间未到,其它线程调用了object.notify()或object.notifyAll() 方法,该线程被被动唤醒但没有获取到锁,则线程进入Blocked(阻塞)状态
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)