Project loom представил службу исполнителя виртуальных потоков Executors.newVirtualThreadPerTaskExecutor()
, которая создает новый виртуальный поток (VT) каждый раз, когда мы отправляем задачу.
У меня есть пара вопросов по этому поводу:
threadFactory.newThread()
Я просмотрел Virtual Thread JEP, и, кажется, там ничего не упоминается по этой теме.
Вам необходимо завершить работу, если вы хотите быть уверены, что служба-исполнитель не принимает новые задачи, и если вы хотите иметь возможность дождаться завершения всех ранее отправленных задач.
А поскольку виртуальные потоки всегда являются потоками демона, ожидание завершения требуется, если вы хотите быть уверены, что все ваши задачи завершены, прежде чем вы выйдете из приложения.
Таким образом, если вас не волнует, были ли задачи, отправленные в службу исполнителя виртуальных потоков, завершены до выхода JVM, вам не нужно ее выключать, но в противном случае вам действительно нужно выключиться и дождаться завершения.
Для очистки виртуальных потоков не требуется ничего особенного. Как только они закончатся, они исчезнут.
@GovindaSakhare Если вы не делаете что-то странное в своей фабрике потоков, вам не нужно ничего делать для очистки потока. В противном случае вам действительно следует задать отдельный вопрос об этом и предоставить минимально воспроизводимый пример, который показывает вашу фабрику нитей и четко объясняет вашу обеспокоенность.
Но это может и не потребоваться, если реализация использует try-with-resources или любой другой способ гарантировать закрытие ресурса. Разве не в этом цель расширения AutoCloseable для самой ExecutorService?
@Naman Хотя это правда, по моему опыту, многие варианты использования службы-исполнителя не позволяют использовать попытку с ресурсами и, как правило, отключаются при каком-то окончательном действии очистки (например, как часть завершения работы приложения). Тем не менее, я не так много работал с функциями Java 21 и совершенно упустил из виду, что теперь в ней есть метод close()
(начиная с Java 19), который выполняет завершение работы и ожидание.
К вашему сведению, реализация close в OpenJDK аналогична шаблонному коду, приведенному в Javadoc ExecutorService, но с тайм-аутом 1 день.
Добавляя к другому ответу , если вы ссылаетесь на пример, приведенный в самом JEP, идеальным способом реализации использования такого ExecutorService
было бы заключить его в оператор try with resources, и в этом случае выключение и ожидание неявно заботятся о:
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 10_000).forEach(i -> {
executor.submit(() -> {
Thread.sleep(Duration.ofSeconds(1));
return i;
});
});
} // executor.close() is called implicitly, and waits
Это справедливо также из-за изменения в рамках Второго предварительного просмотра JEP , чтобы ExecutorService расширял AutoCloseable , раскрывая единственный абстрактный метод close, для которого
Реализация по умолчанию вызывает
shutdown()
и ожидает выполнения задач. полное исполнение сawaitTermination
.
Кроме того, разработчики не должны объединять виртуальные потоки в пул, поэтому вам не нужно беспокоиться об их очистке. ИМХО, большая часть этого была бы реализована, учитывая, что они сокращают усилия по внедрению и обслуживанию приложений, использующих эту функцию.
Обратите внимание, что этот подход блокирует основной поток до тех пор, пока виртуальный поток не завершится.
Как очистить потоки, если я использую ThreadFactory? По какой-то причине я создаю VT с помощью фабрики и украшаю ее перед вызовом потока.