java - CompletableFuture: proper way to run a list of futures, wait for result and handle exception
问题描述
I have a legacy code which have dozen database calls to populate a report, it takes noticeable amount of time which I try to reduce using CompletableFuture
.
I have some doubts that I do things correctly and not overuse this technology.
My code now looks like this:
Start asynchronous population of document sections with many database calls inside each methods
CompletableFuture section1Future = CompletableFuture.supplyAsync(() -> populateSection1(arguments)); CompletableFuture section2Future = CompletableFuture.supplyAsync(() -> populateSection2(arguments)); ... CompletableFuture section1oFuture = CompletableFuture.supplyAsync(() -> populateSection10(arguments));
Then I'm arranging futures in specific order in
arrayList
and joining all of them to make sure that my code will run further only when all futures are finished.List<CompletableFuture> futures = Arrays.asList( section1Future, section2Future, ... section10Future); List<Object> futureResults = futures.stream() .map(CompletableFuture::join) .collect(Collectors.toList());
Then I'm populating PDF document itself with its pieces
Optional.ofNullable((PdfPTable) futureResults.get(0)).ifPresent(el -> populatePdfElement(document, el)); Optional.ofNullable((PdfPTable) futureResults.get(1)).ifPresent(el -> populatePdfElement(document, el)); ... Optional.ofNullable((PdfPTable) futureResults.get(10)).ifPresent(el -> populatePdfElement(document, el));
return document
My concerns are:
1) Is it okay to create and instantiate many Completable Futures in such way? Order them in required sequence in arrayList
, join them to make sure that they are all finished, and then get result by casting them into specific object?
2) Is it okay to run without specifying an executor service but to rely on common ForkJoinPool
? However this code runs in web container, so probably in order to use JTA I need to use container provided thread pool executor via JNDI?
3) If this code is surrounded in try-catch I should be able to catch CompletionException
in main thread, right? Or In order to do that I should declare each features like following:
CompletableFuture.supplyAsync(() -> populateSection1(arguments))
.exceptionally (ex -> {
throw new RuntimeException(ex.getCause());
});
4) Is it possible to overuse CompletableFutures so they become a performance bottleneck itself? Like many futures waits one executor to start running? How to avoid that? Use container provided executor service? If yes, could someone please point me to some best practice on how to correctly configure executor service taking to account processors and memory amount?
5) A memory impact. I read in parallel thread that there can be a problem with OOME as many object are created and garbage collected. Is there a best practice on how to calculate correct amount of memory required for application?
解决方案
推荐阅读
- java - 当我尝试将图像保存到图库时,应用程序不断崩溃
- apache-kafka - 如果 Kafka 集群中的 broker 有不同的设置会发生什么?
- windows - Windows 修补程序的检测脚本
- c# - 从 XPath 创建 XML 文档
- vsts-sync-migrator - 您可以使用该工具持续同步项目积压工作吗?
- excel - Excel宏R1C1公式不保留值
- itext - 如何使用 iTextSharp 将 RTF 文件转换为 PDF 文件
- python - Python日志消息格式不适用于子模块消息
- javascript - 添加 MultiPolygon 几何图形时出现语法错误
- kubernetes - 不使用 ImagePullPolicy 设置为 Always 有什么好处?