正如我们在意见中指明,所消耗的CPU线程是忙着在下面的堆栈:
"pool-9-thread-1" #49 prio=5 os_prio=0 tid=0x00007ffd508e8000 nid=0x3a0c runnable [0x00007ffd188b6000]
java.lang.Thread.State: RUNNABLE
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.poll(ScheduledThreadPoolExecutor.java:809)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1066)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
我已成功通过创建ScheduledThreadPoolExecutor
重现了类似的行为,将其配置为允许核心线程超时,并在很短的延迟时间内安排大量重复任务。它在我的机器上产生大量的CPU,并且jstack
输出类似(有时更深入到poll
方法中)。这段代码也再现:
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
executor.setKeepAliveTime(1, TimeUnit.MINUTES);
executor.allowCoreThreadTimeOut(true);
for (long i = 0; i < 1000; i++) {
executor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
}
}, 0, 1, TimeUnit.NANOSECONDS);
}
现在,我们只需要确定哪些代码设置一个破ScheduledThreadPoolExecutor
。我搜索了RabbitMQ和Netty源代码,但没有发现任何obvoius。它可能是你在自己的代码中做的事情吗?
编辑:作为评价提到的,根本原因是与0
初始化的ScheduledThreadPoolExecutor
这显然会导致CPU自旋OM一些平台。这是在OP的代码中完成的。
如果你可以运行'top -H -p'和'jstack ',你可以看到哪些线程使用CPU和这些线程的堆栈。我还建议运行'jstat -gc '以确保它不是内存问题。 –
感谢您的建议。 top -H -p显示使用所有cpi的1个子进程。 jstack显示了不等待的唯一东西是epollWait和java.net.SocketInputStream.socketRead0(Native Method)。 –
你可以发布'top'和'jstack'的输出吗? enire jstack-output,但是对于'top'最高的5个线程就足够了。 –