簡體   English   中英

如何從CompletableFuture獲取結果

[英]How to get results from the CompletableFuture

下面的代碼中提到的每個“ CompletableFuture.runAsync”都進行一些計算,每次調用“ CompletableFuture.runAsync”時,我都希望得到結果。 或者換句話說,我希望每個“ future0,future1,future2,future3”分別包含對“ CompletableFuture.runAsync”的每次調用的結果

我怎樣才能做到這一點。

*更新

我的要求是,對於CompletableFuture.runAsync的每次調用,我都要進行一些計算,並應返回這些值的ArrayList。 在對CompletableFuture.runAsync的四個調用之后,我想對返回的ArrayList進行一些進一步的計算。

代碼

    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

在這里,我發布一個示例,其中您的工作將返回“ 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提交給executor服務,如下所示:

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]

在旁注中,班級名稱應始終以大寫字母開頭。

除了@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-和地方,應該-您使用-IT-6ac65b7bfbe

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM