Я хочу использовать CompletionService для обработки результатов из серии потоков по мере их заполнения. У меня есть сервис в цикле, чтобы использовать объекты Future, которые он предоставляет по мере их появления, но я не знаю, как лучше всего определить, когда все потоки завершены (и, следовательно, выйти из цикла):Как узнать, когда CompletionService закончен, доставляя результаты?
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
public class Bar {
final static int MAX_THREADS = 4;
final static int TOTAL_THREADS = 20;
public static void main(String[] args) throws Exception{
final ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(MAX_THREADS);
final CompletionService<Integer> service = new ExecutorCompletionService<Integer>(threadPool);
for (int i=0; i<TOTAL_THREADS; i++){
service.submit(new MyCallable(i));
}
int finished = 0;
Future<Integer> future = null;
do{
future = service.take();
int result = future.get();
System.out.println(" took: " + result);
finished++;
}while(finished < TOTAL_THREADS);
System.out.println("Shutting down");
threadPool.shutdown();
}
public static class MyCallable implements Callable<Integer>{
final int id;
public MyCallable(int id){
this.id = id;
System.out.println("Submitting: " + id);
}
@Override
public Integer call() throws Exception {
Thread.sleep(1000);
System.out.println("finished: " + id);
return id;
}
}
}
Я попытался проверить состояние ThreadPoolExecutor, но я знаю, что методы getCompletedTaskCount и getTaskCount являются приблизительными и не следует полагаться. Есть ли лучший способ убедиться, что я получил все Фьючерсы от CompletionService, чем считать их самостоятельно?
Edit: Как связующее звено Nobeh при условии, и this link предполагают, что подсчет числа задач, представленных, то вызов взять(), что во много раз, это путь. Я просто удивлен, что нет способа спросить у CompletionService или его Executor, что осталось вернуть.
Thanks, nobeh. Похоже, что они также просто перебирают количество потоков в своем цикле for (int tasksHandled = 0; tasksHandled
Пример в API использует тот же подход к выполнению take() n раз подряд. http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorCompletionService.html –
Если результаты ExecutionService в другом потоке, кроме задач, были отправлены в Exector, является ли этот поток безопасным? – raffian