CompletableFuture不会关闭线程

时间:2018-09-05 14:02:12

标签: java multithreading asynchronous

我的异步方法有问题。它工作正常,但是线程数一直在增加。

这是我的代码示例:

ExecutorService executorService = Executors.newFixedThreadPool(marketplaces.size());

public void createCache() {
        List<CompletableFuture<List<OrderResponseDto>>> futures = marketplaces.stream().map(
                m -> CompletableFuture.supplyAsync(m::trades, executorService)
                        .applyToEither(timeoutAfter(TIMEOUT_SECONDS, TimeUnit.SECONDS), Function.identity())
                        .exceptionally(error -> {
                            log.warn("Trades failed {}", error);
                            return Collections.emptyList();
                        })
        ).collect(toList());

    Map<TradePlatform, List<OrderResponseDto>> collect = futures.stream()
            .map(CompletableFuture::join)
            .flatMap(List::stream)
            .collect(groupingBy(OrderResponseDto::getMarketplace));
    marketplaceCache.putAll(collect); 
}

位于GitHub上的完整项目:https://github.com/rublin/KarboMarketplaceExplorer

Direct link上课

这里是一个test,涵盖了此行为。

1 个答案:

答案 0 :(得分:0)

总结评论中列出的发现:

这是由timeoutAfter()方法引起的线程泄漏(请参见链接的源代码)。

此方法每次调用时都会创建一个只有一个线程的新线程池,但是没有什么可以关闭该池并因此停止线程。

由于timeoutAfter()CompletableFuture中创建的每个createCache()被(可能)调用一次,因此线程的总数不断增加。

一种解决方法是在应用程序生存期内重用线程池,并确保它们在退出时已正确关闭(另​​一个考虑因素是如何调整线程池的大小以及使用哪种类型的线程池,尤其是当提交给他们的任务可能会阻止)。

另请参阅内森·休斯(Nathan Hughes)对问题的评论。