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

时间:2015-06-20 21:06:03

标签: java multithreading concurrency

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()行时,我们是否在那里等待所有结果生成?

3 个答案:

答案 0 :(得分:5)

  

执行给定的任务,返回持有他们的期货清单   完成后的状态和结果。 Future.isDone()适用于每个人   返回列表的元素。请注意,已完成的任务可能具有   正常终止或通过抛出异常终止。结果   如果同时修改给定集合,则此方法未定义   此操作正在进行中。

期货只能在执行完成时完成,因此此方法只能在任务执行完毕后返回。

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

查看invokeAlljava.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.