Ответ 1
Как мы отметили в комментариях, поток, потребляющий процессор, занят в следующем стеке:
"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
, сконфигурировав его, чтобы разрешить тайм-ауты ядра и планировать множество повторяющихся задач с небольшой задержкой. Это дает много процессора на моей машине, а вывод 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. Может быть, это то, что вы делаете в своем собственном коде?
Изменить. Как упоминалось в комментариях, основной причиной было ScheduledThreadPoolExecutor
, инициализированное с помощью 0
, которое, по-видимому, может вызвать переключение CPU на некоторые платформы. Это было сделано в OP-коде.