invokeAll()不愿意接受Collection <Callable <T >>

Yos*_*ale 8 java callable executorservice

我无法理解为什么这段代码不能编译

ExecutorService executor = new ScheduledThreadPoolExecutor(threads);

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

错误消息是:

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

listCollectionDocFeeder,它实现了Callable<Boolean>-这是怎么回事?

Jon*_*eet 18

只是为了扩大saua的答案......

在Java 5中,该方法被声明为:

invokeAll(Collection<Callable<T>> tasks) 
Run Code Online (Sandbox Code Playgroud)

在Java 6中,该方法声明为:

invokeAll(Collection<? extends Callable<T>> tasks) 
Run Code Online (Sandbox Code Playgroud)

通配符的差异非常重要 - 因为它List<DocFeeder> 一个Collection<? extends Callable<T>>但它不是一个Collection<Callable<T>>.考虑一下这种方法会发生什么:

public void addSomething(Collection<Callable<Boolean>> collection)
{
    collection.add(new SomeCallable<Boolean>());
}
Run Code Online (Sandbox Code Playgroud)

这是合法的 - 但如果您可以addSomething使用a 来调用List<DocFeeder>它会非常糟糕,因为它会尝试将非DocFeeder添加到列表中.

所以,如果你遇到Java 5,你需要创建一个List<Callable<Boolean>>来自你的List<DocFeeder>.


Joa*_*uer 7

该代码与Java 6编译完美,但无法使用Java 5编译

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

但改变list这样:

Collection<Callable<Boolean>> list = new LinkedList<Callable<Boolean>>();
Run Code Online (Sandbox Code Playgroud)

使其适用于Java 5和Java 6.