Java 8中并发异步方法后跟并行执行方法
在花了一天时间学习java并发API之后,我仍然不太明白如何在CompletableFuture和ExecutorService类的帮助下创建以下功能:
当我在REST端点上收到请求时,我需要:
- 启动一个异步任务(包括DB查询、筛选等),它将在最后给我一个字符串URL列表
- 同时,用HTTP OK回复REST调用方,请求已收到,我正在处理它
- 异步任务完成后,我需要将HTTP请求(使用REST调用方提供的负载)发送到我从作业中获得的URL。最多URL的数量大约是100个,所以我需要这些并行发生李>
- 理想情况下,我有一些同步计数器来计算有多少http请求成功/失败,我可以将此信息发送回REST调用方(我需要发送回的URL在请求负载中提供)李>
我有构建块(方法如:getMatchingObjectsFromDB(callerPayload)、GetURL(ResultToGetMachingObjects)、sendHttpRequest(Url、methodType)等…)我已经为这些写过了,我只是不太明白如何将步骤1和步骤3结合在一起。我将在步骤1中使用CompletableFuture.supplyAsync()
,然后我将需要CompletableFuture.thenComponse
方法来开始步骤3,但我不清楚如何使用此API实现并行。但是ExecutorService executor = Executors.newWorkStealingPool();
非常直观,它根据可用的处理能力创建线程池,并且可以通过invokeAll()
方法提交任务
我怎样才能同时使用CompletableFuture
和ExecutorService
?或者,如何保证使用CompletableFuture
并行执行任务列表?演示代码片段将不胜感激。谢谢
# 1 楼答案
您应该使用
join()
等待所有线程完成创建
Map<String, Boolean> result
以存储请求结果在控制器中:
为您服务:
然后使用
.join()
等待所有线程(请记住,您的服务已经在自己的线程中执行)然后,您可以通过访问
result
映射来确定哪一个成功/失败编辑
请张贴您的程序代码,以便其他人也能理解您
我已经阅读了您的代码,以下是所需的修改:
对不起,在我之前的回答中,我没有清理它。这只是我脑子里的一个临时想法,最后我忘了删除:D
只需从代码中删除它
您的映射应该是
ConcurrentHashMap
,因为您稍后将同时修改它如果您的代码仍然不能按预期工作,我建议删除
parallelStream()
部分CompletableFuture
和parallelStream
使用公共forkjoin池。我想游泳池已经用完了您应该为您的
CompletableFuture
创建自己的池:并使用该池执行您的请求:
# 2 楼答案
为了便于完成,在清理和测试之后,这里是代码的相关部分(感谢Mạ新罕布什尔州奎伊ế唐古伊ễn) :
Rest控制器类:
服务类别:
调试这段代码比通常要困难一些,有时代码会神奇地停止。为了解决这个问题,我只将绝对必要的代码部分放入异步任务中,并确保任务中的代码使用线程安全的东西。而且,一开始我是个哑巴,
EventHandlerService.class
中的方法使用了synchronized
关键字,这导致服务类方法中的CompletableFuture无法执行,因为它默认使用线程池