Java ThreadPoolExexecutor使用流和可调用对象

时间:2018-12-24 05:58:11

标签: java java-stream java.util.concurrent threadpoolexecutor

我有一个实现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,所以我仍然需要关闭执行器吗?

2 个答案:

答案 0 :(得分:2)

您需要的是Collectors.summingLong

.collect(Collectors.summingLong(r -> r));

r -> r只是ToLongFunction的情况下,您的long返回的每个Long中都有一个Callable

  

而且,由于我正在调用invokeAll,因此我是否还需要关闭执行器?

ExecutorService.invokeAll没有记录自动关机。所以你需要自己关闭它

答案 1 :(得分:2)

您可以使用Stream.mapToLongfuture.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