ExecutorService executorService = Executors.newSingleThreadExecutor();
Set<Callable<String>> callables = new HashSet<Callable<String>>();
callables.add(new Callable<String>() {
public String call() throws Exception {
return "Task 1";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
return "Task 2";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
return "Task 3";
}
});
List<Future<String>> futures = executorService.invokeAll(callables);
for(Future<String> future : futures){
System.out.println("future.get = " + future.get());
}
这段代码。我的问题是&#34;是invokeAll()一个阻止调用&#34;? 我的意思是,当代码运行到invokeAll()行时,我们是否在那里等待所有结果生成?
答案 0 :(得分:5)
执行给定的任务,返回持有他们的期货清单 完成后的状态和结果。 Future.isDone()适用于每个人 返回列表的元素。请注意,已完成的任务可能具有 正常终止或通过抛出异常终止。结果 如果同时修改给定集合,则此方法未定义 此操作正在进行中。
期货只能在执行完成时完成,因此此方法只能在任务执行完毕后返回。
它可以抛出InterruptedException也表示阻塞动作。
查看invokeAll
中java.util.concurrent.AbstractExecutorService
的实施情况(评论内联):
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException {
if (tasks == null)
throw new NullPointerException();
ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
boolean done = false;
try {
for (Callable<T> t : tasks) {
RunnableFuture<T> f = newTaskFor(t);
futures.add(f);
execute(f);
}
for (int i = 0, size = futures.size(); i < size; i++) {
Future<T> f = futures.get(i);
if (!f.isDone()) {
try {
f.get(); // <== *** BLOCKS HERE ***
} catch (CancellationException ignore) {
} catch (ExecutionException ignore) {
}
}
}
done = true;
return futures;
} finally {
if (!done)
for (int i = 0, size = futures.size(); i < size; i++)
futures.get(i).cancel(true);
}
}
事实上,在Javadoc-Specese似乎难以破译的情况下,查看参考实现是您在这些情况下通常应该做的事情。 (需要注意的是,某些实现细节不是规范的一部分。)
答案 1 :(得分:1)
你的意思是,如果父线程将等待使用ExecutorService
调用创建的所有线程?然后回答是肯定的,父线程将等待,一旦所有线程完成,您将获得Futures
对象的列表,该列表将保存每个线程执行的结果。
请参阅下面的ExecutorService.invokeAll()
执行给定的任务,返回持有他们的期货清单 状态和结果完成后。
答案 2 :(得分:0)
InvokeAll 方法阻塞,直到所有任务完成并返回期货列表, 解决方案: 如果我们不希望这种情况发生并继续执行程序,我们可以循环遍历任务并将其传递给 ExecutorService 的 Submit 方法并将其添加到未来对象列表中
ExecutorService es=Executors.newFixedThreadPool(4);
List<SampleClassimplementingCallable<String>> tasks=new ArrayList<>();
List<Future<String>> futures=new ArrayList<>();
for(SampleClassimplementingCallable<String> s:tasks)
{
//This Won't Block the Calling Thread and We will get the list of futures
futures.add(es.submit(s));
}
However, When the Futures are retrieved from the list and get method is called on indivual future object ,then the thread is blocked.