You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java线程优先级对JVM调度是否生效?生产者消费者案例疑问

问题原因分析

1. 代码逻辑存在明确错误

  • 锁持有逻辑错误:你将Thread.sleep(10)写在了synchronized同步块内部,而sleep方法执行期间不会释放持有的对象锁。也就是说无论是生产者还是消费者线程,只要进入同步块,就会独占共享队列的锁至少10ms,这段时间另一个线程完全无法获取锁操作队列,优先级设置完全无法发挥作用。比如消费者消费完最后一个元素后,抱着锁睡10ms,这期间生产者根本拿不到锁生产新元素,自然就会触发队列为空的等待逻辑。
  • 条件判断写法不规范:你使用if判断队列是否满/空,而标准的wait调用逻辑必须用while循环判断,避免线程被虚假唤醒后直接执行后续逻辑导致队列越界问题,虽然这不是本次问题的核心,但属于潜在bug。

2. Java线程优先级本身的作用限制

Java线程优先级本质只是给JVM和操作系统调度器的参考建议,没有任何规范要求高优先级线程必须获得更多的调度资源,实际效果高度依赖底层操作系统实现:

  • Windows系统虽然支持优先级抢占,但系统自带动态优先级调整机制,会自动提升长时间未获得调度的线程、IO等待线程的优先级,你手动设置的优先级很容易被系统覆盖。
  • Linux平台下的OpenJDK默认不启用线程优先级,只有添加JVM参数-XX:+UseThreadPriorities、并且运行程序的用户有足够权限调整线程调度策略时,优先级设置才会生效。
修复建议

首先将两个线程run方法里的Thread.sleep(10)代码移到synchronized同步块外部,确保线程操作完队列后立刻释放锁,给另一个线程执行的机会。其次将队列状态判断的if替换为while,避免虚假唤醒问题。
修复后的核心代码示例:

// 生产者run方法示例
public void run() {
    while (true) {
        synchronized (sharedQueue) {
            // 替换为while判断
            while (sharedQueue.size() == maxCapicity) {
                System.out.println("Producer : Table is full, waiting for consumers to consume");
                try {
                    sharedQueue.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            prdNumber++;
            sharedQueue.add(prdNumber);
            System.out.println("Producer produced = " + prdNumber);
            sharedQueue.notify();
        }
        // sleep移到同步块外
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
// 消费者run方法同理调整

修复后再次运行,你会发现生产者高优先级的效果会体现出来,队列频繁为空的情况会大幅减少,但依然无法完全避免,这是Java线程调度本身的特性决定的。

内容的提问来源于stack exchange,提问作者prakash kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.15 03:54:05