简体   繁体   English

CompleteableFuture Java 8 异常行为

[英]CompleteableFuture Java 8 unusual behavior

I noticed some unusual behavior with CompleteableFutures in Java 8 with streaming.我注意到 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());

This code above takes 4*5000 = 20 seconds to execute, so this means the futures are waiting on one another.上面的代码需要 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);

This code however, runs in 5 seconds meaning futures are running in parallel.然而,这段代码在 5 秒内运行,这意味着期货是并行运行的。

What I don't understand: In the second example I get a list of futures explicitly, then do a join, which takes 5 seconds, the first example I keep it streaming through and it seems to wait.我不明白的是:在第二个示例中,我明确地获得了一个期货列表,然后进行连接,这需要 5 秒,第一个示例我让它流过,它似乎在等待。

What's the reasoning behind this?这背后的原因是什么?

Streams don't necessarily do one stage, then the next.流不一定做一个阶段,然后是下一个阶段。 They can compose operations in any order they choose.他们可以按照他们选择的任何顺序组成操作。

So for example,例如,

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

can end up being run the same way as最终可以以相同的方式运行

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

...which would have the results you see: the futures are generated one at a time and immediately joined, instead of all being generated up front and then joined. ...这将产生您看到的结果:期货一次生成一个并立即加入,而不是全部先生成然后加入。

In point of fact, if you're not doing something async, it's usually more efficient to do it the second way.事实上,如果你不做一些异步的事情,那么第二种方式通常会有效。 That way, the stream framework doesn't have to store all the results of f, then store all the results of g: it can only store the results of g(f(e)).这样,stream 框架就不必存储 f 的所有结果,然后存储 g 的所有结果:它只能存储 g(f(e)) 的结果。 The stream framework can't know you're doing async code, so it does the normal efficient thing. stream 框架无法知道您正在执行异步代码,因此它执行正常高效的操作。

I think the issue is with the second map function call in the original snippet.我认为问题在于原始代码段中的第二个 map function 调用。 The map function is serial and hence calls the CF blocking function join for each one of the elements in the source array one after another. map function 是串行的,因此为源数组中的每个元素一个接一个地调用 CF 阻塞 function 连接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM