Чем можно объяснить взаимоблокировку, возникающую только в виртуальных потоках?
Я столкнулся с тупиком при использовании исполнителя на основе виртуальных потоков. Проблема возникает, когда я использую 50 потоков, но не 20. Проблема не проявляется, когда я не использую виртуальные потоки.
Мне нужны идеи и рекомендации по устранению неполадок и решению проблемы взаимоблокировки, уникальной для виртуальных потоков, особенно учитывая отсутствие этой проблемы, когда виртуальные потоки не используются.
private static final ExecutorService taskExecutor =0 Executors.newFixedThreadPool(CONCURRENT_WORKERS);
против
private static final ExecutorService taskExecutor = Executors.newFixedThreadPool(CONCURRENT_WORKERS, Thread.ofVirtual().factory());
Служба исполнителя заключена в CompletionService.
private static final CompletionService<Data> completionService = new ExecutorCompletionService<>(taskExecutor)
Кажется, что основной поток ждет бесконечно при первом вызовеcompletionService.take()
.
Вот соответствующий фрагмент кода.
for (int taskIndex = 0; taskIndex < TASK_COUNT; taskIndex++) {
completionService.submit(this::doTask);
}
log.info("Submitted all {} tasks to the executor, waiting.", TASK_COUNT);
try {
for (int taskIndex = 0; taskIndex < TASK_COUNT; taskIndex++) {
Future<Data> future = completionService.take();
try {
var data = future.get();
storeData(data);
} catch (ExecutionException e) {
log.warn("Error executing task", e);
}
}
}
В чем может быть причина проблемы?
РЕДАКТИРОВАТЬ: похоже, это вызвано проблемой пула HTTP-соединений. Я использую httpclient-4.5.14.
Внутренне этот клиент используетsynchronized
что, насколько я понимаю, является проблемой для виртуальных потоков, поскольку они закрепляют поток платформы. Я не знаю, может ли это быть причиной тупика, поскольку я не вижу ни ошибок, ни странных вещей в дампе потока.
Испытания: я пытался использовать -Djdk.tracePinnedThreads=full для проверки закрепленной темы, но до сих пор безуспешно.