当前位置: 首页 > news >正文

线程的状态对比:等待、驻留、监视

目录
  • 线程的状态对比:等待、驻留、监视
    • 等待(waiting)和监视(blocked)的区别
    • 等待(waiting)和监视(blocked)都算是阻塞吗?
    • 线程池没有任务来时,所有核心线程会是等待(waiting)状态?
      • 不同类型的等待
      • 总结
    • 等待(Wait)和驻留(Park)的区别
      • 代码示例对比
      • 总结
    • Park状态的出现时机
    • Park状态和Park线程的区别分析

线程的状态对比:等待、驻留、监视

等待(waiting)和监视(blocked)的区别

等待(waiting)和监视(blocked)的区别 ?

官方线程状态定义

public enum State {NEW,RUNNABLE,BLOCKED,    // 阻塞WAITING,    // 等待TIMED_WAITING, // 超时等待TERMINATED
}

核心区别对比

特性 BLOCKED(阻塞) WAITING(等待)
触发条件 等待进入synchronized同步块 调用Object.wait()、Thread.join()、LockSupport.park()
唤醒方式 获取到监视器锁时自动唤醒 需要其他线程主动唤醒(notify/notifyAll)
锁的状态 在竞争锁,但还没拿到 已经释放了锁,在等待条件
使用场景 简单的互斥访问 复杂的线程协作
超时机制 无超时,一直等待锁 可以有超时(TIMED_WAITING)或无超时
总结

关键区别记忆点:

  • BLOCKED:"我想进去,但门锁着,我在门口等着"
  • WAITING:"我主动休息了,你好了叫我"

游戏服务器中的指导原则:

  1. BLOCKED过多 → 锁竞争激烈,需要优化锁策略
  2. WAITING正常 → 线程协作,是设计的一部分
  3. 监控两者比例 → BLOCKED应该远少于WAITING
  4. 优先使用java.util.concurrent → 比synchronized + wait/notify更高效

等待(waiting)和监视(blocked)都算是阻塞吗?

都算是阻塞吗?

从Java线程状态机来看:BLOCKED和WAITING是两种不同的状态,但都可以被认为是广义的"阻塞"。

// Java线程状态机中的关系
RUNNABLE → BLOCKED     // 等待锁 → 广义阻塞
RUNNABLE → WAITING     // 主动等待 → 广义阻塞  
RUNNABLE → TIMED_WAITING // 超时等待 → 广义阻塞

详细分析

  1. 从CPU执行角度:都是阻塞
public class CpuPerspective {public static void main(String[] args) {// 无论是BLOCKED还是WAITING状态:// - 线程都不在CPU上执行指令 ✓// - 都不消耗CPU计算资源 ✓// - 都在等待某种条件满足 ✓// 因此从CPU调度器角度看,它们都是"不运行"的状态}
}
  1. 从阻塞原因角度:有重要区别
阻塞类型 原因 恢复条件
同步阻塞 (BLOCKED) 竞争同步锁 锁可用时自动恢复
等待阻塞 (WAITING) 主动放弃CPU 需要其他线程显式唤醒
I/O阻塞 等待I/O操作 I/O完成时恢复

线程池没有任务来时,所有核心线程会是等待(waiting)状态?

线程池中没有任务时,核心线程会处于WAITING状态,但具体机制有所不同。

不同类型的等待

  1. 使用LinkedBlockingQueue的线程池
public class LinkedBlockingQueueExample {public static void main(String[] args) {ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 30, TimeUnit.SECONDS,new LinkedBlockingQueue<>()  // 无界队列);executor.prestartAllCoreThreads();// 空闲线程状态: WAITING// 阻塞在: java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject// 具体是: LinkedBlockingQueue.take() 方法中的condition.await()}
}
  1. 使用SynchronousQueue的线程池
public class SynchronousQueueExample {public static void main(String[] args) {ExecutorService executor = Executors.newCachedThreadPool();// 内部使用SynchronousQueue// 空闲线程状态: WAITING  // 阻塞在: SynchronousQueue的transfer方法// 等待其他线程提交任务}
}
  1. 使用ArrayBlockingQueue的线程池
public class ArrayBlockingQueueExample {public static void main(String[] args) {ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 30, TimeUnit.SECONDS,new ArrayBlockingQueue<>(10)  // 有界队列);// 空闲线程状态: WAITING// 阻塞在: ArrayBlockingQueue的condition.await()}
}

不同的队列不同的实现:

/**
* LinkedBlockingQueue: 
* - 空闲线程: WAITING on ConditionObject
* - 队列空时阻塞在take()
* 
* SynchronousQueue:
* - 空闲线程: WAITING on transfer stack
* - 没有缓冲区,直接传递
* 
* DelayQueue:
* - 空闲线程: TIMED_WAITING
* - 等待特定延迟时间
*//**
* 空闲的核心线程资源占用:
* - 内存: 每个线程约1MB栈内存 (通过-Xss设置)
* - 内核资源: 每个线程占用操作系统线程结构
* - CPU: 几乎为0 (WAITING状态不消耗CPU)
* 
* 示例: 10个核心线程空闲
* - 内存: 10MB
* - CPU: 0%
* - 状态: 全部WAITING
*/

总结

是的,线程池没有任务时,核心线程处于WAITING状态,这是正常且期望的行为:

正常现象:

  • 所有空闲核心线程都处于WAITING状态
  • 阻塞在工作队列的获取方法上(如take())
  • 不消耗CPU资源,只占用少量内存

简单来说:WAITING的空闲线程就像待命的士兵,随时准备执行任务,这是线程池高效工作的基础机制!

等待(Wait)和驻留(Park)的区别

方面 Wait Park
所属包 java.lang.Object java.util.concurrent.locks.LockSupport
需要锁吗 ✅ 必须在synchronized块内 ❌ 不需要持有锁
会释放锁吗 ✅ 会释放锁 ❌ 不涉及锁操作
唤醒方式 notify()/notifyAll() unpark(thread)
超时支持 wait(timeout) parkNanos(timeout)
中断响应 ✅ 抛出InterruptedException ✅ 直接返回,不抛异常

无论是等待还是驻留,线程在WAITING状态下的资源占用模式是相同的:

  • CPU占用:几乎为0
  • 内存占用:固定(线程栈大小)
  • 系统资源:少量内核结构

代码示例对比

  1. Wait 的使用
public class WaitExample {private static final Object lock = new Object();public void doWait() throws InterruptedException {synchronized (lock) {  // 必须先获得锁System.out.println("准备wait,会释放锁");lock.wait();       // 释放锁,进入WAITING状态System.out.println("被notify唤醒了,重新获得锁");}}public void doNotify() {synchronized (lock) {  // 必须获得同一把锁lock.notify();     // 唤醒一个等待线程}}
}
  1. Park 的使用
public class ParkExample {public void doPark() {System.out.println("准备park,不需要锁");LockSupport.park();    // 直接挂起,不需要锁System.out.println("被unpark唤醒了");}public void doUnpark(Thread thread) {LockSupport.unpark(thread);  // 随时可以唤醒指定线程}
}

总结

简单记忆:

  • Wait:"老式"方式,必须配合synchronized使用,会释放锁
  • Park:"现代"方式,更灵活,不需要锁,性能更好

在并发编程中的选择:

  • 需要与synchronized配合时用 Wait
  • java.util.concurrent包中的高级并发工具中用 Park
  • 需要精确控制特定线程时用 Park

VisualVM中看到:

  • "Wait" → 传统的wait()/notify()机制
  • "Park" → 现代的LockSupport.park()/unpark()机制

两者都是等待,但底层机制和适用场景完全不同!🎯

Park状态的出现时机

  • Java 5 引入JUC包时出现
  • 主要在各种并发工具内部使用
  • 线程池、队列、锁等底层实现

现状:

  • Park/Unpark: 现代并发首选,框架广泛使用
  • ⚠️ Wait/Notify: 遗留代码、简单场景、教学示例
  • 🎯 推荐: 直接使用JUC高级工具,而不是手动park/wait

简单历史总结:

1996-2004: wait/notify 为主流
2004-现在: park/unpark + JUC工具 成为主流
现在: 95%+的新代码使用JUC,而不是直接wait/notify

现代Java开发中,我们更应该关注如何使用好JUC工具,而不是纠结于底层的park/wait选择!🎯

Park状态和Park线程的区别分析

方面 Park状态 Park线程
定义 线程的瞬时状态 线程的身份性质
时间范围 短暂的,可变化的 相对持久的
关注点 线程当前在干什么 线程的用途和角色

简单判断:

  • 如果线程偶尔park一下 → 只是处于Park状态
  • 如果线程主要工作就是park等待 → 是Park线程

Park线程的判断标准:

  1. 主要工作时间处于Park状态 (>80%时间)
  2. 设计用途就是等待事件/任务
  3. 执行的工作是次要的,等待是主要的
http://www.hskmm.com/?act=detail&tid=31531

相关文章:

  • [论文阅读] AI + 软件工程(Debug)| 告别 “猜 bug”:TreeMind 用 LLM+MCTS 破解 Android 不完整报告复现难题 - 实践
  • 软件开发初学
  • 2025年振动电机厂家最新权威推荐榜:高频/防爆/低噪声/卧式/直流/节能/侧板式/三段式全系列深度解析与选购指南
  • 测试面试官亲述:打动我的不是技能,而是这种思维
  • 大数据分析之MySQL学习1
  • 2025年GEO(AI搜索优化)源头厂家终极口碑推荐榜
  • 2025年GEO(AI搜索优化)源头厂家Top10权威推荐榜
  • 10.15
  • 2025 年丝杆升降机厂家行业推荐榜:螺旋丝杆升降机/蜗杆丝杆升降机/蜗轮丝杆升降机/聚焦精准传动需求,德州德特机械设备有限公司成优选
  • 深度解读:2025中国太阳能板TOP10榜单背后的格局颠覆与逻辑
  • Docker - 部署Consul 新
  • 重新定义行业:2025年中国市场最值得关注的十大太阳能品牌
  • 2025年变位机厂家最新权威推荐榜:焊接变位机/防位移变位机/重型变位机,精准定位与高效协同技术解析
  • 使用TCL脚本快速创建Quartus工程
  • kv cache缓存
  • 为什么笔记本电脑突然变得很卡?固态硬盘突然变慢是什么原因?
  • 用 Uni-app 开发 C3 继续教育题库系统:静态资源导入、响应式交互与考试逻辑实现全解析
  • 2025年上海律师服务最新权威推荐榜:经侦律师,民事/刑事律师,经济/婚姻律师,法务律师,负债律师事务所专业解析
  • 2025 年永磁电机厂家推荐台州市台成机电,单相永磁电机,三相永磁电机,变频永磁电机,稀土永磁电机,直流永磁电机,无刷永磁电机,风机永磁电机,节能永磁电机,高效永磁电机公司推荐
  • 2025年实验室净化/手术室净化/洁净室工程厂家最新权威推荐榜:专业建设与无尘车间装修一站式解决方案
  • 深入理解 `itertools`:分类解析常用函数 (Effective Python 第36条) - 教程
  • linux配置环境变量
  • assert的基本用法
  • 1688代发铺货规格匹配设置
  • 2025年整平机厂家最新推荐排行榜,精密整平机,数控整平机,自动整平机,板材整平机源头厂家专业选购指南
  • task2
  • KiloCode 与 Claude Code 在长上下文文件写入操作中的稳定性差异深度解析
  • 2025年机械加工厂家最新权威推荐榜:钣金/焊接/零件/非标自动化/精密金属加工,专业定制与技术创新实力解析
  • 2025年10月15号随笔
  • Ubuntu20.04安装NVIDIA显卡驱动、CUDA Toolkit、cuDNN步骤(二) - 指南