为ExecutorService创建一个包装器invokeAll()

时间:2014-04-07 21:17:13

标签: java

我正在使用此代码示例:

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

executorService.shutdown();

我正在尝试为此代码编写一个包装类,它将用于泛型类型,并且在展开时可以转换为String / int / etc。

我遇到的问题是将集合传递给invokeAll()方法。我在将自定义活动添加到callable设置时遇到了一些麻烦。

理想情况下,我希望能够分离出我的代码,以便我可以调用方法而不是声明内部类。有没有办法声明从我的自定义方法返回的对象集合,这些对象可以传递给invokeAll()方法?

我正在尝试一些不同的收藏,但不断得到:

The method invokeAll(Collection<? extends Callable<T>>) in the type ExecutorService is not applicable for the arguments (Collection<Object>)

1 个答案:

答案 0 :(得分:2)

由于invokeAll()Generic Method,您可能需要使用特殊语法来指明T的类型。以下调用应该清除您的错误:

List<Future<String>> futures = executorService.<String>invokeAll(callables);

虽然我不得不说,我能够在独立程序中按原样运行您的示例代码......

通常,这不是问题,但如果使用类型推断定义集合(从Java 7开始可用)可能会成为问题。例如,如果您通过以下方式初始化Collection

Set<Callable<String>> callables = new HashSet<>();

这意味着编译器可能需要更加努力地弄清楚你的集合的类型(尽管这对我来说也很有用)。在您的情况下尤其如此,因为您声称正在尝试编写通用包装类。泛型方法的棘手几乎肯定会起作用。您可能还想查看关于通用方法的this Java教程。