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

Java ScheduledExecutorService在Linux下CPU占满100%且无任务执行问题

问题根源与解决方案

这是Java 8u40版本的已知bug(编号JDK-8075300),刚好被你踩中了——当ScheduledThreadPoolExecutor的核心线程数设为0时,工作线程会陷入无休的忙循环,直接把CPU拉满到100%。

为什么会触发?

你创建调度器时指定了corePoolSize=0:

executor = Executors.newScheduledThreadPool(0, (r) -> new Thread(r, "Scheduler"));

在Java 8u40的实现逻辑里,当核心线程数为0时,线程池的getTask()方法会调用DelayedWorkQueue.poll(0, TimeUnit.NANOSECONDS)(因为默认的keepAliveTime是0)。而这个版本的DelayedWorkQueue在处理超时为0的场景时,不会进入休眠等待,而是不断循环检查队列是否有任务,导致线程一直处于RUNNABLE状态,疯狂占用CPU。

你在Windows用的Java 8u45已经修复了这个bug,所以一切正常,这也侧面验证了问题的版本相关性。

怎么解决?

有两个简单靠谱的方案:

  • 把核心线程数改成1:既然你要长期运行定时任务,保留至少1个核心线程是合理的,这样线程不会被回收,也不会触发忙循环:

    executor = Executors.newScheduledThreadPool(1, (r) -> new Thread(r, "Scheduler"));
    
  • 升级Linux上的JDK版本:这个bug在Java 8u60及以后的版本中已经被官方修复,升级后问题自然消失。

从堆栈看问题

你提供的堆栈信息也完全符合这个bug的表现:

Thread[Scheduler,5,app] RUNNABLE CPU (msecs) = 15020099 
java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.poll(ScheduledThreadPoolExecutor.java:809) 
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1066) 
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127) 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
java.lang.Thread.run(Thread.java:745)

线程一直卡在DelayedWorkQueue.poll方法里,且持续处于RUNNABLE状态,没有任何休眠,这就是典型的忙循环特征。

内容的提问来源于stack exchange,提问作者Tim B

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:04:16