是invokeAll()在java 7中的阻塞调用

Buf*_*lls 5 java concurrency multithreading

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());
}
Run Code Online (Sandbox Code Playgroud)

对于这段代码.我的问题是"是invokeAll()阻塞调用"?我的意思是,当代码运行到invokeAll()行时,我们是否在那里等待所有结果生成?

the*_*472 6

执行给定的任务,返回完成所有状态和结果的Futures列表.对于返回列表的每个元素,Future.isDone()都为true.请注意,已完成的任务可能正常终止或通过抛出异常终止.如果在此操作正在进行时修改了给定集合,则此方法的结果是不确定的.

期货只能在执行完成时完成,因此该方法只能在执行任务时返回.

它可以抛出InterruptedException也表示阻塞动作.

查看invokeAllin 的实现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);
    }
}
Run Code Online (Sandbox Code Playgroud)

事实上,在Javadoc-Specese似乎难以破译的情况下,查看参考实现是您在这些情况下通常应该做的事情.(需要注意的是,一些实现细节不是规范的一部分.)