Smithsonian
Smithsonian

Reputation: 173

invokeAll vs CompletionService

I am having a class that is accessed by multiple threads, each thread request one method of this class. Each method in turn performs number of Callables. This class uses threadPool from ExecutorService to execute these Callables through invokeAll((Collection>) executableTasks) method. The setup looks like this:

public MyClass {
private final ExecutorService threadPool = Runtime.getRuntime().availableProcessors();

public void method1() {
 List<SomeObject> results = new ArrayList<>();
 List<Callable<Void>> tasks = new ArrayList<Callable<Void>>();
 tasks.add(new Callable<Void>(){ ... results.add(someObject);} );
 threadPool.invokeAll(tasks);
}

public void method2() {
 List<SomeObject> results = new ArrayList<>();
 List<Callable<Void>> tasks = new ArrayList<Callable<Void>>();
 tasks.add(new Callable<Void>(){ ... results.add(someObject);} );
 threadPool.invokeAll(tasks);
}

}

I am confused if this will execute tasks in class concurrently or invokeAll() will block execution till tasks in one method completes(means execution will happen concurrently inside methods but not at class level)? Or Should I use CompletionService to find out the corresponding results of tasks?

Upvotes: 1

Views: 2129

Answers (3)

Cody A. Ray
Cody A. Ray

Reputation: 6027

ExecutorService#invokeAll executes all the tasks concurrently, but the call itself blocks until all the tasks complete.

For example, let's say you have three tasks that take 6 sec, 2 sec, and 10 sec to complete. If you were to execute these synchronously, it would take at least 6 + 2 + 10 = 18 seconds. However, using invokeAll (on a sufficiently large thread pool), this could take as little as the longest time, or 10 seconds.

This means that the methods method1() and method2() are both blocking methods because of the use of invokeAll(). When you call method1(), it will block until all of the requests added into the list of callables are complete. Same goes for method2(). If these methods are called from different threads, then the tasks in both methods will execute concurrently.

If you want the methods to be asynchronous, you'll want to call threadPool.submit(callable) individually for each task inside the methods and collect the returned futures in a list. You could either return a List or use a CompletionService to help for this, yes.

PS - this line in your example won't work:

ExecutorService threadPool = Runtime.getRuntime().availableProcessors();

I think you want this instead:

ExecutorService threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

Hope this helps.

Upvotes: 2

vishal_aim
vishal_aim

Reputation: 7854

To me, this will execute tasks in class concurrently. invokeAll() waits until all its tasks are finished but that is for the current thread, while this thread is waiting, other thread can execute its tasks concurrently

Upvotes: 0

Jans
Jans

Reputation: 11250

According to the Java Specification invokeAll execute all tasks concurrently independently of one another. and repeated calls to invokeAll will do the same, That is, the call to invokeAll not block the execution of tasks.

Visit:http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/AbstractExecutorService.html

Upvotes: -1

Related Questions