Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is invokeAll() a blocking call in java 7

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());
}

For this code piece. My question is "is invokeAll() a blocking call "? I mean, when code ran to invokeAll() line, are we bloking there to wait for all result been generated?

like image 656
BufBills Avatar asked Jun 20 '15 21:06

BufBills


1 Answers

Executes the given tasks, returning a list of Futures holding their status and results when all complete. Future.isDone() is true for each element of the returned list. Note that a completed task could have terminated either normally or by throwing an exception. The results of this method are undefined if the given collection is modified while this operation is in progress.

Futures can only be done when execution is finished, therefore this method can only return when the tasks have been executed.

That it can throw an InterruptedException is also indicative of a blocking action.

Looking at the implementation of invokeAll in java.util.concurrent.AbstractExecutorService (comment inline):

// from OpenJDK source; GPL-2.0-with-classpath-exception
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);
    }
}

In fact, looking at a reference implementation is what you generally should do in these cases when the Javadoc-Specese appears to be difficult to decipher. (with the caveat in mind that some implementation details are not part of the spec.)

like image 165
the8472 Avatar answered Nov 13 '22 23:11

the8472