zoukankan      html  css  js  c++  java
  • CompletableFuture.allOf方法,future的handler有没有执行问题

    场景

    在分片上传的时候,有返回对应的etag,所以,我需要在分片上传完成之后,对返回的数据进行封装,封装完成后调最后的完成接口.
    出现问题,总是缺少部分分片,偶尔会报错…

    模拟

    for循环创建CompletableFuture,然后执行allOf方法看看:

    public static void main(String[] args) throws InterruptedException {
            List<CompletableFuture> comlist = new ArrayList<>();
            int size = 3;
            CountDownLatch countDownLatch = new CountDownLatch(size);
            for (int i = 0; i < size; i++) {
                final int res = i;
                CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {
                    try {
                        TimeUnit.SECONDS.sleep(3);
                        System.out.println(System.currentTimeMillis() + ":" + res + "执行完成");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return res + "";
                });
                f1.whenCompleteAsync((x, y) -> {
                    try {
                        TimeUnit.SECONDS.sleep(1);
                        System.out.println(System.currentTimeMillis() + ":" + x + "回调执行完成");
                        countDownLatch.countDown();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                });
                comlist.add(f1);
            }
    
            CompletableFuture<Void> all = CompletableFuture.allOf(comlist.toArray(new CompletableFuture[size]));
            //阻塞,直到所有任务结束。任务complete就会执行,handler里面不一定会执行..
            System.out.println(System.currentTimeMillis() + ":阻塞");
            all.join();
            System.out.println(System.currentTimeMillis() + ":阻塞结束");
            countDownLatch.await();
            System.out.println("回调都结束...");
        }
    

     输出:

    结论

    发现当执行完成之后,allof返回的就会结束,并不会等待回调方法也执行完成…
    所以,一般使用allof方法的时候,都是消费Action,一般不会对结果进行处理,如果对结果进行处理,那肯定会发生错误…

    那么怎么办呢??????嘿嘿~

    我们可以把上面代码里的这一段做个修改:

    输出:

     也就是是说:

    上面代码中CompletableFuture.allOf()是等待所有传入的任务是否完成,你传入的的comlist中的future都已经完成了,就已经算完成阶段了。如果你想要的结果是等待把回调执行完成,你可以给f1添加回调生成f2,比如f2=f1.whenCompleteAsync,然后把f2放入comlist中。

    那为什么会这样呢?嘿嘿~

    原因就是:每个CompletableFuture添加诸如thenApply的回调后会生成一个新的CompletableFuture对象,这个新的CompletableFuture对象的完成阶段是thenApply执行后才会被认为是完成阶段。

  • 相关阅读:
    jq 京东跳楼效果
    *Sum of NestedInteger
    **Minimum Window Substring & String类问题模板
    **Word Ladder
    *Longest Increasing Subsequence
    *Kth Largest Element in an Array
    *Permutations II
    *Implement Stack using Queues
    *Paint House II
    *Paint Fence
  • 原文地址:https://www.cnblogs.com/47Gamer/p/13684194.html
Copyright © 2011-2022 走看看