我有一个实现Callable
的类,并且它有一个覆盖call
并返回Long
的方法。
我将List
中的Callable<Long>
创建为
List<Callable<Long>> callables = new ArrayList<>();
for (File fileEntry : folder.listFiles()) {
callables.add(new DataProcessor(fileEntry));
我有
ExecutorService threadPoolExecutor = Executors.newFixedThreadPool(10);
我打电话
threadPoolExecutor.invokeAll(callables)
.stream()
.map(future -> {
try {
return future.get();
} catch (Exception e) {
throw new IllegalStateException(e);
}
})
.collect(Collectors.toLong(/* what goes here? */));
我想做的是对future.get()
的所有返回值求和。
此外,由于我正在调用invokeAll,所以我仍然需要关闭执行器吗?
答案 0 :(得分:2)
您需要的是Collectors.summingLong
:
.collect(Collectors.summingLong(r -> r));
在r -> r
只是ToLongFunction
的情况下,您的long
返回的每个Long
中都有一个Callable
。
而且,由于我正在调用invokeAll,因此我是否还需要关闭执行器?
ExecutorService.invokeAll
没有记录自动关机。所以你需要自己关闭它
答案 1 :(得分:2)
您可以使用Stream.mapToLong
将future.get
映射为LongStream
,然后以以下方式找到流的sum
:
long sum = threadPoolExecutor.invokeAll(callables)
.stream()
.mapToLong(future -> {
try {
return future.get();
} catch (Exception e) {
throw new IllegalStateException(e);
}
}) // LongStream
.sum(); // sum of the stream
注意 :这简化了使用Collectors.summingLong
的流API调用链。遍历集合时,可以避免创建冗余的临时对象。
旁边 :您也可以collect
Callable
的形式:
List<Callable<Long>> callables = fileList.stream()
.map(fileEntry -> new DataProcessor(fileEntry))
.collect(Collectors.toList());
由于我正在调用invokeAll,因此我是否仍需要关闭 执行者?
是的,您必须关闭ExecutorService
。您还可以使用isShutDown()
API来确认相同的状态:
System.out.println(threadPoolExecutor.isShutdown()); // would return false