Java线程调度由JVM协同操作系统实现,以抢占式为主,优先级仅为OS建议值;时间片轮转保障同优先级线程公平性;状态驱动调度,仅RUNNABLE线程参与竞争;虚拟线程由JVM用户态调度器接管,提升I/O密集型场景吞吐。

Java线程调度是JVM协同操作系统,决定哪个线程在何时获得CPU执行权的过程。它不直接控制硬件,而是通过设置优先级、触发状态转换、配合OS调度器来影响线程的运行时机。关键在于:Java线程本身没有独立的“调度算法实现”,它的调度行为最终由底层操作系统(如Linux的CFS或Windows线程调度器)主导,JVM主要做映射、封装和状态管理。
抢占式为主,优先级仅作提示
Java默认采用抢占式调度:高优先级线程就绪时,可能中断当前低优先级线程的执行。但要注意——
- 线程优先级(1~10)只是向OS传递的建议值,不同系统映射方式不同(例如Linux中Java的10级可能只映射到少数几个nice值)
- 高优先级不保证先执行,也不保证执行更久,只提高被选中的概率
- 过度依赖setPriority()容易引发线程饥饿,尤其在大量同优先级线程竞争时
- 默认优先级是5(Thread.NORM_PRIORITY),多数场景无需手动调整
时间片轮转是基础执行节奏
当多个同优先级线程处于RUNNABLE状态,操作系统会按时间片轮转分配CPU:
- 每个线程分得一个固定或动态调整的时间片(毫秒级)
- 时间片用尽后,线程被强制让出CPU,进入就绪队列尾部,等待下一轮调度
- 若线程主动阻塞(如sleep、wait、I/O等待),会立即释放CPU,不等时间片耗尽
- 这种机制保障了基本公平性,避免单一线程长期霸占资源
状态驱动调度,不是代码直控
线程能否被调度,取决于其是否处于RUNNABLE状态。其他状态均无法参与CPU竞争:
立即学习“Java免费学习笔记(深入)”;
- BLOCKED:正等待锁(synchronized或Lock),需等持有锁线程释放
- WAITING / TIMED_WAITING:调用了wait()、join()、sleep()等,必须靠notify、interrupt或超时唤醒才能回到RUNNABLE
- NEW / TERMINATED:不在调度范围内
- 注意:sleep()不释放锁,yield()只对同优先级线程“礼让”,都不是可靠同步手段
虚拟线程带来调度范式转变
Java 21+ 的虚拟线程(Virtual Thread)改变了传统调度逻辑:
- 不再一对一绑定OS线程,而是由JVM在ForkJoinPool上复用少量平台线程作为“载体”
- I/O阻塞时自动挂起虚拟线程,载体线程立刻腾出执行其他任务,实现高吞吐
- 调度完全由JVM用户态调度器接管,脱离OS线程调度瓶颈
- 适合大量短任务、I/O密集型场景(如Web请求),但CPU密集型任务仍应使用平台线程
基本上就这些。调度行为本质是JVM与OS协作的结果,写代码时更应关注线程状态流转、合理使用同步工具和选择合适线程模型,而非纠结于优先级数字。










