簡體   English   中英

CompleteableFuture Java 8 異常行為

[英]CompleteableFuture Java 8 unusual behavior

我注意到 Java 8 中的 CompleteableFutures 有一些不尋常的行為。

String [] arr = new String[]{"abc", "def", "cde", "ghj"};
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        List<String> lst =
                Arrays.stream(arr)
                        .map(r ->
                                CompletableFuture.supplyAsync(() -> {
                                    try {
                                        Thread.sleep(5000);
                                        return "e";
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                    return null;
                                }, executorService)
                        )
                        .map(CompletableFuture::join)
                        .collect(Collectors.toList());

上面的代碼需要 4*5000 = 20 秒來執行,所以這意味着期貨正在相互等待。

 String [] arr = new String[]{"abc", "def", "cde", "ghj"};
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        List<CompletableFuture<String>> lst =
                Arrays.stream(arr)
                        .map(r ->
                                CompletableFuture.supplyAsync(() -> {
                                    try {
                                        Thread.sleep(5000);
                                        return "d";
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                    return null;
                                }, executorService)
                        )
                        .collect(Collectors.toList());

        List<String> s =
                lst
                        .stream()
                        .map(CompletableFuture::join)
                        .collect(Collectors.toList());

        System.out.println(s);

然而,這段代碼在 5 秒內運行,這意味着期貨是並行運行的。

我不明白的是:在第二個示例中,我明確地獲得了一個期貨列表,然后進行連接,這需要 5 秒,第一個示例我讓它流過,它似乎在等待。

這背后的原因是什么?

流不一定做一個階段,然后是下一個階段。 他們可以按照他們選擇的任何順序組成操作。

例如,

Arrays.stream(array).map(e -> f(e)).map(e -> g(e)).collect(toList());

最終可以以相同的方式運行

Arrays.stream(array).map(e -> g(f(e))).collect(toList());

...這將產生您看到的結果:期貨一次生成一個並立即加入,而不是全部先生成然后加入。

事實上,如果你不做一些異步的事情,那么第二種方式通常會有效。 這樣,stream 框架就不必存儲 f 的所有結果,然后存儲 g 的所有結果:它只能存儲 g(f(e)) 的結果。 stream 框架無法知道您正在執行異步代碼,因此它執行正常高效的操作。

我認為問題在於原始代碼段中的第二個 map function 調用。 map function 是串行的,因此為源數組中的每個元素一個接一個地調用 CF 阻塞 function 連接。

暫無
暫無

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

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