Подтвердить что ты не робот

Исполнители Java: дождитесь завершения задачи.

Мне нужно отправить несколько задач, а затем дождаться их, пока не будут доступны все результаты. Каждый из них добавляет String в Vector (который по умолчанию синхронизируется). Затем мне нужно начать новую задачу для каждого результата в Vector, но мне нужно сделать это, только когда все предыдущие задачи перестали выполнять свою работу.

Я хочу использовать Java Executor, в частности, я попытался использовать Executors.newFixedThreadPool(100), чтобы использовать фиксированное число потоков (у меня есть переменное число задач, которое может быть 10 или 500), но я новичок с исполнителями и Я не знаю, как ждать завершения задачи. Это что-то вроде псевдокода моей программы:

ExecutorService e = Executors.newFixedThreadPool(100);
while(true){

/*do something*/

for(...){
<start task>
}

<wait for all task termination>

for each String in result{
<start task>
}

<wait for all task termination>
}

Я не могу выполнить e.shutdown, потому что я некоторое время (правда), и мне нужно повторно использовать executorService...

Вы можете мне помочь? Можете ли вы предложить мне путеводитель/книгу о исполнителях java?

4b9b3361

Ответ 1

ExecutorService предоставляет вам механизм для одновременного выполнения нескольких задач и получения коллекции объектов Future назад (представляющих асинхронное вычисление задачи).

Collection<Callable<?>> tasks = new LinkedList<Callable<?>>();
//populate tasks
for (Future<?> f : executorService.invokeAll(tasks)) { //invokeAll() blocks until ALL tasks submitted to executor complete
    f.get(); 
}

Если у вас есть Runnable вместо Callable s, вы можете легко превратить Runnable в Callable<Object> с помощью метода:

Callable<?> c = Executors.callable(runnable);

Ответ 2

Можете ли вы предложить мне путеводитель/книгу о java-исполнители

Я могу ответить на эту часть:

Java Concurrency на практике Брайана Гетца (с Тимом Пайерлсом, Джошуа Блох, Джозеф Боубэр, Дэвид Холмс и Дуг Лиа), скорее всего, ваш лучший выбор.

l3bFn.jpg

Это не только об исполнителях, но и охватывает пакет java.util.concurrent в целом, а также основные понятия и методы Concurrency и некоторые дополнительные темы, такие как модель памяти Java.

Ответ 3

Вместо отправки Runnable или Callable в Executor напрямую и сохранения соответствующих возвращаемых значений Future я бы рекомендовал использовать реализацию CompletionService для извлечения каждого Future , когда он завершает. Этот подход отделяет производство задач от потребления завершенных задач, позволяя, например, создавать новые задачи в потоке производителя за определенный промежуток времени.

Collection<Callable<Result>> workItems = ...
ExecutorService executor = Executors.newSingleThreadExecutor();
CompletionService<Result> compService = new ExecutorCompletionService<Result>(executor);

// Add work items to Executor.
for (Callable<Result> workItem : workItems) {
  compService.submit(workItem);
}

// Consume results as they complete (this would typically occur on a different thread).
for (int i=0; i<workItems.size(); ++i) {
  Future<Result> fut = compService.take(); // Will block until a result is available.
  Result result = fut.get(); // Extract result; this will not block.
}

Ответ 4

Когда вы отправляете службе исполнителя, вы получите объект Future.

Сохраните эти объекты в коллекции, а затем вызовите get() по очереди. get() блокируется до завершения базового задания, и поэтому результатом является то, что вызов get() для каждого будет завершен после завершения всех базовых заданий.

например.

Collection<Future> futures = ...
for (Future f : futures) {
   Object result = f.get();
   // maybe do something with the result. This could be a
   // genericised Future<T>
}
System.out.println("Tasks completed");

Как только все это закончится, начните свое второе представление. Обратите внимание, что это может быть не оптимальное использование пула потоков, поскольку оно станет бездействующим, а затем вы его повторно заселяете. Если возможно, попробуйте и не забудьте заняться делами.

Ответ 5

ExecutorService executor = ...
//submit tasks
executor.shutdown(); // previously submitted tasks are executed, 
                     // but no new tasks will be accepted
while(!executor.awaitTermination(1, TimeUnit.SECONDS))
    ;

Нет простого способа сделать то, что вы хотите, без создания пользовательского ExecutorService.