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
相关产品推荐
相关产品推荐

