如何从 CompletableFuture 获取结果
How to get results from the CompletableFuture
下面代码中提到的每个 "CompletableFuture.runAsync" 都会进行一些计算,我希望每次调用 "CompletableFuture.runAsync" 时都能得到结果。或者换句话说,我希望每个 "future0,future1,future2,future3" 分别包含对 "CompletableFuture.runAsync" 的每次调用的结果
我该怎么做。
*更新:
我的要求是,每次调用 CompletableFuture.runAsync 我都会进行一些计算,并且应该返回这些值的 ArrayList。在 CompletableFuture.runAsync 的四个调用之后,我想对返回的 ArrayLists 进行一些进一步的计算。
代码:
if (this.laplaceImgList != null) {
if (!this.laplaceImgList.isEmpty()) {
if (this.laplaceImgList.size() == 3) {
//executor
ExecutorService orintMapExe;
CompletableFuture<Void> future0 = null;
CompletableFuture<Void> future1 = null;
CompletableFuture<Void> future2 = null;
CompletableFuture<Void> future3 = null;
orintMapExe = Executors.newFixedThreadPool(1);
future0 = CompletableFuture.runAsync(new orintMapRun(SysConsts.ORINT_DEG_ZERO , this.laplaceImgList), orintMapExe);
future1 = CompletableFuture.runAsync(new orintMapRun(SysConsts.ORINT_DEG_45 , this.laplaceImgList), orintMapExe);
future2 = CompletableFuture.runAsync(new orintMapRun(SysConsts.ORINT_DEG_90 , this.laplaceImgList), orintMapExe);
future2 = CompletableFuture.runAsync(new orintMapRun(SysConsts.ORINT_DEG_135 , this.laplaceImgList), orintMapExe);
CompletableFuture.allOf(future0,future1,future2,future3).join();//blocks the main thread till future0, and future1 finishes
我在这里发布了一个示例,您的工作将 return 一个 Future
并且您将获得您提供的值列表。正如您所期望的结果(实际上是 List),它实现了 Callable
.
public class OrintMapRun implements Callable<List<Integer>> {
final int partOne, partTwo;
final List<Integer> resultList = new ArrayList<>();
public OrintMapRun(int partOne, int partTwo) {
this.partOne = partOne;
this.partTwo = partTwo;
}
@Override
public List<Integer> call() throws Exception {
resultList.add(partOne);
resultList.add(partTwo);
Thread.sleep(5000); //simulate some computation
return resultList;
}
}
现在您需要将那些 Callables
提交给执行程序服务,如下所示:
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService orintMapExe = Executors.newFixedThreadPool(4);
List<Future<List<Integer>>> futures = new ArrayList<>();
futures.add(orintMapExe.submit(new OrintMapRun(10, 10)));
futures.add(orintMapExe.submit(new OrintMapRun(20, 20)));
futures.add(orintMapExe.submit(new OrintMapRun(30, 30)));
futures.add(orintMapExe.submit(new OrintMapRun(40, 40)));
orintMapExe.shutdown();
try {
orintMapExe.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e) {
e.printStackTrace();
}
for(Future<List<Integer>> future : futures) {
List<Integer> result = future.get();
System.out.println(result);
}
}
一旦您获得所有期货的结果,它将是:
[10, 10]
[20, 20]
[30, 30]
[40, 40]
旁注 class 名称应始终以大写字母开头。
除了来自@i_am_zero的答案,您还可以使用CompletionService,它是简单ExecutorService的包装器。 CompletionService 的好处是你总能拿到最早完成的 Future<> 对象,后面的操作不会被最后完成的任务阻塞。根据@i_am_zero的回答,简单的改进如下:
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService orintMapExe = Executors.newFixedThreadPool(4);
CompletionService service = new ExecutorCompletionService(orintMapExe);
List<Future<List<Integer>>> futures = new ArrayList<>();
futures.add(orintMapExe.submit(new OrintMapRun(10, 10)));
futures.add(orintMapExe.submit(new OrintMapRun(20, 20)));
futures.add(orintMapExe.submit(new OrintMapRun(30, 30)));
futures.add(orintMapExe.submit(new OrintMapRun(40, 40)));
for(int i=0; I< futures.size();i++) {
List<Integer> result = service.take().get();
System.out.println(result);
}
}
在大多数情况下,CompletionService 应该比准系统 ExecutorService 更受欢迎,除非您不关心性能。
有一些很好的文章解释了好处,例如 https://dzone.com/articles/executorservice-vs。
CompletionService 足以解决您的问题,但如果您有兴趣,CompletableFuture, I wrote up a simple blog on one scenario which is a great fit for using it: https://medium.com/@zhongzhongzhong/beauty-of-completablefuture-and-where-should-you-use-it-6ac65b7bfbe
下面代码中提到的每个 "CompletableFuture.runAsync" 都会进行一些计算,我希望每次调用 "CompletableFuture.runAsync" 时都能得到结果。或者换句话说,我希望每个 "future0,future1,future2,future3" 分别包含对 "CompletableFuture.runAsync" 的每次调用的结果
我该怎么做。
*更新:
我的要求是,每次调用 CompletableFuture.runAsync 我都会进行一些计算,并且应该返回这些值的 ArrayList。在 CompletableFuture.runAsync 的四个调用之后,我想对返回的 ArrayLists 进行一些进一步的计算。
代码:
if (this.laplaceImgList != null) {
if (!this.laplaceImgList.isEmpty()) {
if (this.laplaceImgList.size() == 3) {
//executor
ExecutorService orintMapExe;
CompletableFuture<Void> future0 = null;
CompletableFuture<Void> future1 = null;
CompletableFuture<Void> future2 = null;
CompletableFuture<Void> future3 = null;
orintMapExe = Executors.newFixedThreadPool(1);
future0 = CompletableFuture.runAsync(new orintMapRun(SysConsts.ORINT_DEG_ZERO , this.laplaceImgList), orintMapExe);
future1 = CompletableFuture.runAsync(new orintMapRun(SysConsts.ORINT_DEG_45 , this.laplaceImgList), orintMapExe);
future2 = CompletableFuture.runAsync(new orintMapRun(SysConsts.ORINT_DEG_90 , this.laplaceImgList), orintMapExe);
future2 = CompletableFuture.runAsync(new orintMapRun(SysConsts.ORINT_DEG_135 , this.laplaceImgList), orintMapExe);
CompletableFuture.allOf(future0,future1,future2,future3).join();//blocks the main thread till future0, and future1 finishes
我在这里发布了一个示例,您的工作将 return 一个 Future
并且您将获得您提供的值列表。正如您所期望的结果(实际上是 List),它实现了 Callable
.
public class OrintMapRun implements Callable<List<Integer>> {
final int partOne, partTwo;
final List<Integer> resultList = new ArrayList<>();
public OrintMapRun(int partOne, int partTwo) {
this.partOne = partOne;
this.partTwo = partTwo;
}
@Override
public List<Integer> call() throws Exception {
resultList.add(partOne);
resultList.add(partTwo);
Thread.sleep(5000); //simulate some computation
return resultList;
}
}
现在您需要将那些 Callables
提交给执行程序服务,如下所示:
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService orintMapExe = Executors.newFixedThreadPool(4);
List<Future<List<Integer>>> futures = new ArrayList<>();
futures.add(orintMapExe.submit(new OrintMapRun(10, 10)));
futures.add(orintMapExe.submit(new OrintMapRun(20, 20)));
futures.add(orintMapExe.submit(new OrintMapRun(30, 30)));
futures.add(orintMapExe.submit(new OrintMapRun(40, 40)));
orintMapExe.shutdown();
try {
orintMapExe.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e) {
e.printStackTrace();
}
for(Future<List<Integer>> future : futures) {
List<Integer> result = future.get();
System.out.println(result);
}
}
一旦您获得所有期货的结果,它将是:
[10, 10]
[20, 20]
[30, 30]
[40, 40]
旁注 class 名称应始终以大写字母开头。
除了来自@i_am_zero的答案,您还可以使用CompletionService,它是简单ExecutorService的包装器。 CompletionService 的好处是你总能拿到最早完成的 Future<> 对象,后面的操作不会被最后完成的任务阻塞。根据@i_am_zero的回答,简单的改进如下:
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService orintMapExe = Executors.newFixedThreadPool(4);
CompletionService service = new ExecutorCompletionService(orintMapExe);
List<Future<List<Integer>>> futures = new ArrayList<>();
futures.add(orintMapExe.submit(new OrintMapRun(10, 10)));
futures.add(orintMapExe.submit(new OrintMapRun(20, 20)));
futures.add(orintMapExe.submit(new OrintMapRun(30, 30)));
futures.add(orintMapExe.submit(new OrintMapRun(40, 40)));
for(int i=0; I< futures.size();i++) {
List<Integer> result = service.take().get();
System.out.println(result);
}
}
在大多数情况下,CompletionService 应该比准系统 ExecutorService 更受欢迎,除非您不关心性能。 有一些很好的文章解释了好处,例如 https://dzone.com/articles/executorservice-vs。
CompletionService 足以解决您的问题,但如果您有兴趣,CompletableFuture, I wrote up a simple blog on one scenario which is a great fit for using it: https://medium.com/@zhongzhongzhong/beauty-of-completablefuture-and-where-should-you-use-it-6ac65b7bfbe