Спящий поток, отправляющий задачи, не приостанавливает отправленные задачи
Ваш вопрос не ясен, но, по-видимому, он связан с вашим ожиданием того, что добавление Thread.sleep
после каждого вызова executorService.execute
приведет к спячке всех потоков службы-исполнителя.
for ( int i = 1 ; i <= filesInDirectory ; i++ ) {
executorService.execute( new Importer( service ) ); // Executor service assigns this task to one of the background threads in its backing pool of threads.
Thread.sleep( Duration.ofMillis( 100 ).toMillis() ) ; // Sleeping this thread doing the looping. *Not* sleeping the background threads managed by the executor service.
}
Ваше ожидание неверно.
Этот Thread.sleep
спит в потоке, выполняющем цикл for
.
Служба-исполнитель имеет собственный резервный пул потоков. На эти потоки не влияет Thread.sleep
какой-то другой поток. Эти фоновые потоки будут спать только в том случае, если вы вызовете Thread.sleep
внутри кода, работающего в каждом из этих потоков.
Итак, вы передаете первую задачу службе-исполнителю. Служба-исполнитель немедленно отправляет эту работу одному из своих вспомогательных потоков. Эта задача выполняется немедленно (если поток доступен немедленно и не занят предыдущими задачами).
После назначения этой задачи ваш цикл for
спит в течение ста миллисекунд, в этом примере кода, показанном здесь. Пока цикл for
находится в спящем режиме, службе-исполнителю не назначаются никакие другие задачи. Но пока цикл for
спит, отправленная задача выполняется в фоновом потоке. Этот фоновый поток не спит.
В конце концов, ваш поток цикла for
просыпается, назначает вторую задачу и снова засыпает. Тем временем фоновый поток выполняется на полной скорости впереди.
Таким образом, приостановка потока, отправляющего задачи, не приостанавливает уже отправленные задачи.
Ожидание выполнения отправленных задач
Ваш заголовок спрашивает:
ExecutorService должен дождаться завершения пакета taksk перед повторным запуском
После отправки задач вызовите shutdown
и awaitTermination
в службе-исполнителе. После этих вызовов ваш код блокируется, ожидая завершения/отмены/сбоя всех отправленных задач.
ExecutorService executorService = Executors.newVirtualThreadExecutor() ;
… submit tasks to that executor service …
executorService.shutdown() ;
executorSerivce.awaitTermination() ; // At this point, the flow-of-control blocks until the submitted tasks are done.
System.out.println( "INFO - Tasks on background threads are done. " + Instant.now() );
Я бы предложил использовать файл ExecutorService#submit
вместо метода ExecutorService#execute
. Разница в том, что первый метод возвращает объект Future
. Вы можете собирать эти Future
объекты при отправке задач службе-исполнителю. После shutdown
и awaitTermination
вы можете изучить свою коллекцию объектов Future
, чтобы проверить статус их завершения.
Проект Ткацкий станок
Если Project Loom удастся, такой код будет немного проще и понятнее. Экспериментальные сборки технологии Project Loom доступны сейчас на основе раннего доступа к Java 17. Команда Loom ищет обратную связь сейчас.
В Project Loom ExecutorService
становится AutoCloseable
. Это означает, что мы можем использовать синтаксис try-with-resources для автоматического вызова нового метода close
для ExecutorService
. Этот close
метод сначала блокируется до тех пор, пока все задачи не будут завершены/отменены/сбоем, а затем отключает службу-исполнитель. Нет необходимости звонить shutdown
или awaitTermination
.
Кстати, в Project Loom тоже есть виртуальные нити (волокна). Это, вероятно, значительно повысит производительность вашего кода, потому что это требует большого количества блокировок для ввода-вывода в хранилище и доступа к базе данных.
try (
ExecutorService executorService = Executors.newVirtualThreadExecutor() ;
)
{
… submit tasks to that executor service …
}
// At this point, with Project Loom technology, the flow-of-control blocks until the submitted tasks are done.
// Also, the `ExecutorService` is automatically closed/shutdown by this point, via try-with-resources syntax.
System.out.println( "INFO - Tasks on background threads are done. " + Instant.now() );
С помощью Project Loom вы можете собрать возвращенные Future
объектов таким же образом, как описано выше, чтобы проверить статус завершения.
У вас есть другие проблемы в вашем коде. Но вы не раскрыли достаточно, чтобы ответить на них все.
19.03.2021