Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

invokeAll() is not willing to accept a Collection<Callable<T>>

I fail to understand why this code won't compile

ExecutorService executor = new ScheduledThreadPoolExecutor(threads);

class DocFeeder implements Callable<Boolean> {....} 
... 
List<DocFeeder> list = new LinkedList<DocFeeder>();
list.add(new DocFeeder(1));
...
executor.invokeAll(list);

The error msg is:

The method invokeAll(Collection<Callable<T>>) in the type ExecutorService is 
not applicable for the arguments (List<DocFeeder>)  

list is a Collection of DocFeeder, which implements Callable<Boolean> - What is going on?!

like image 272
Yossale Avatar asked Dec 16 '08 08:12

Yossale


People also ask

What does invokeAll do in Java?

invokeAll. Executes the given tasks, returning a list of Futures holding their status and results when all complete or the timeout expires, whichever happens first. Future. isDone() is true for each element of the returned list.

Is Executorservice invokeAll blocking?

invokeAll() does indeed run the callable tasks in it's own thread, but it also blocks waiting for the tasks to complete. submit() does not block.


2 Answers

Just to expand on saua's answer a little...

In Java 5, the method was declared as:

invokeAll(Collection<Callable<T>> tasks) 

In Java 6, the method is declared as:

invokeAll(Collection<? extends Callable<T>> tasks) 

The wildcarding difference is very important - because List<DocFeeder> is a Collection<? extends Callable<T>> but it's not a Collection<Callable<T>>. Consider what would happen with this method:

public void addSomething(Collection<Callable<Boolean>> collection)
{
    collection.add(new SomeCallable<Boolean>());
}

That's legal - but it's clearly bad if you can call addSomething with a List<DocFeeder> as it will try to add a non-DocFeeder to the list.

So, if you are stuck with Java 5, you need to create a List<Callable<Boolean>> from your List<DocFeeder>.

like image 61
Jon Skeet Avatar answered Oct 04 '22 02:10

Jon Skeet


That code compiles perfectly fine with Java 6, but fails to compile with Java 5 giving

Foo.java:9: cannot find symbol
symbol  : method invokeAll(java.util.List)
location: interface java.util.concurrent.ExecutorService
executor.invokeAll(list);
        ^
1 error

However changing the list like this:

Collection<Callable<Boolean>> list = new LinkedList<Callable<Boolean>>();

Makes it work on both Java 5 and Java 6.

like image 37
Joachim Sauer Avatar answered Oct 04 '22 04:10

Joachim Sauer