【问题标题】:How to get results from the CompletableFuture如何从 CompletableFuture 获取结果
【发布时间】:2015-07-19 12:40:39
【问题描述】:

下面代码中提到的每个“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

【问题讨论】:

  • orintMapRun 在做什么?请粘贴代码。
  • @akhil_mittal 它是可运行的类
  • 如果你想返回一些结果,你应该使用Callable。为什么需要CompletableFuture?这可以通过将任务提交给执行器服务来完成。
  • @akhil_mittal 那么,我需要的只是将可运行对象更改为可调用对象?
  • 我们一般用futures来表示一些其他线程运行的代码。但是,如果您想创建一个 Future 来表示您知道会发生的某个事件,但您没有任何基于此未来的异步作业,那么您可以使用 CompletableFuture,它将在该事件上完成。

标签: java multithreading threadpool executorservice countdownlatch


【解决方案1】:

除了@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,我写了一篇关于一个非常适合使用它的场景的简单博客:https://medium.com/@zhongzhongzhong/beauty-of-completablefuture-and-where-should-you-use-it-6ac65b7bfbe

【讨论】:

    【解决方案2】:

    在这里,我发布了一个示例,您的工作将返回 Future,并且您将获得您提供的值列表。正如您所期望的结果(实际上是列表),它实现了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]

    在旁注中,类名应始终以大写字母开头。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多