正如我們在意見中指明,所消耗的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個線程就足夠了。 –