我一直在尝试实现一个异步过程,其中父方法调用一个子方法,而子方法又会调用三个不同的方法。我希望所有的过程都是异步完成的,也就是说,在子方法中的这三个调用并行进行之后,控件应该返回到父方法,并继续执行它的其余部分。
我有这段代码,经过测试后效果很好。
public ReturnSomething parent(){
child();
...//rest to UI
}
private void child(){
ExecutorService executorService = Executors.newFixedThreadPool(3);
Runnable service1 = () -> {
MyFileService.service1();
};
Runnable service2 = () -> {
MyFileService.service2();
};
Runnable service3 = () -> {
MyFileService.service3();
};
executorService.submit(service1);
executorService.submit(service2);
executorService.submit(service3);
}
现在,我的领导要求我使用这个,而不是。
public ReturnSomething parent(){
child();
...//rest to UI
}
private void child(){
CompletableFuture.supplyAsync(() -> MyFileService.service1();
CompletableFuture.supplyAsync(() -> MyFileService.service2();
CompletableFuture.supplyAsync(() -> MyFileService.service3();
}
我知道完全未来是从Java8开始的,但是第二个代码怎么会比第一个更好呢?因为,对于ExecutorService,我没有调用get()方法,所以我不会等待aysnc响应。那么,有人能解释一下有什么区别吗?
首先,后者提高了可读性。其次,我不确定您是否急于(以一般方式解释您的问题)每次parent()调用child()时都创建了ExecutorService的新实例。
除此之外,的未来也是完整的。SupplySync
返回一种非常方便的方法来获取对公共共享池的引用,这将缓解您的生活,除非您想对池中的线程服务您的请求的方式进行特定的自定义。
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinPool.html#commonPool--
你不是在等待两种情况的结果。
第二种方法的优点是简单地减少了模板。这就是runAsync()
和supplyAsync()
的好处。
但是如果您实际上没有返回任何值,那么应该使用runAsync()
第二种方法也提供了等待所有期货的能力CompletableFuture.allOf()
。这在第一种情况下也不存在。
从功能上讲,这两种方法大致相同:
然而,从技术上讲,有一些微妙的区别:
ForkJoinPool
。如果不想传递,则必须将executor作为supplyAsync()
的第二个参数传递
CompletableFuture
API允许使用thenApply()
,thencose()
等轻松链接更多调用。因此,它比ExecutorService返回的简单Future
更灵活。提交()
CompletableFuture
可以使用return CompletableFuture从child()方法轻松返回未来。allOf(以前创建的期货)
关于可读性,这是一个优先选择的问题,但是如果你想要相同的代码,
CompletableFuture
方法可能会被认为在你将其格式化后可读性会降低一些。比较:
executorService.submit(MyFileService::service1);
executorService.submit(MyFileService::service2);
executorService.submit(MyFileService::service3);
具有
CompletableFuture.supplyAsync(MyFileService::service1, executorService);
CompletableFuture.supplyAsync(MyFileService::service2, executorService);
CompletableFuture.supplyAsync(MyFileService::service3, executorService);