zoukankan      html  css  js  c++  java
  • CompletableFuture方法总结

    1、 runAsync 和 supplyAsync方法

    CompletableFuture 提供了四个静态方法来创建一个异步操作。 

    1 public static CompletableFuture<Void> runAsync(Runnable runnable)
    2 public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
    3 public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
    4 public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)

     没有指定Executor的方法会使用ForkJoinPool.commonPool() 作为它的线程池执行异步代码。如果指定线程池,则使用指定的线程池运行。以下所有的方法都类同。

    • runAsync方法不支持返回值。
    • supplyAsync可以支持返回值。

    示例

     1 //无返回值
     2 public static void runAsync() throws Exception {
     3     CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
     4         try {
     5             TimeUnit.SECONDS.sleep(1);
     6         } catch (InterruptedException e) {
     7         }
     8         System.out.println("run end ...");
     9     });
    10     
    11     future.get();
    12 }
    13 
    14 //有返回值
    15 public static void supplyAsync() throws Exception {         
    16     CompletableFuture<Long> future = CompletableFuture.supplyAsync(() -> {
    17         try {
    18             TimeUnit.SECONDS.sleep(1);
    19         } catch (InterruptedException e) {
    20         }
    21         System.out.println("run end ...");
    22         return System.currentTimeMillis();
    23     });
    24 
    25     long time = future.get();
    26     System.out.println("time = "+time);
    27 }

    2、计算结果完成时的回调方法

    当CompletableFuture的计算结果完成,或者抛出异常的时候,可以执行特定的Action。主要是下面的方法: 

    1 public CompletableFuture<T> whenComplete(BiConsumer<? super T,? super Throwable> action)
    2 public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action)
    3 public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action, Executor executor)
    4 public CompletableFuture<T> exceptionally(Function<Throwable,? extends T> fn)

    可以看到Action的类型是BiConsumer<? super T,? super Throwable>它可以处理正常的计算结果,或者异常情况。

    whenComplete 和 whenCompleteAsync 的区别:
    whenComplete:是执行当前任务的线程执行继续执行 whenComplete 的任务。
    whenCompleteAsync:是执行把 whenCompleteAsync 这个任务继续提交给线程池来进行执行。

    示例

     1 public static void whenComplete() throws Exception {
     2     CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
     3         try {
     4             TimeUnit.SECONDS.sleep(1);
     5         } catch (InterruptedException e) {
     6         }
     7         if(new Random().nextInt()%2>=0) {
     8             int i = 12/0;
     9         }
    10         System.out.println("run end ...");
    11     });
    12     
    13     future.whenComplete(new BiConsumer<Void, Throwable>() {
    14         @Override
    15         public void accept(Void t, Throwable action) {
    16             System.out.println("执行完成!");
    17         }
    18         
    19     });
    20     future.exceptionally(new Function<Throwable, Void>() {
    21         @Override
    22         public Void apply(Throwable t) {
    23             System.out.println("执行失败!"+t.getMessage());
    24             return null;
    25         }
    26     });
    27     
    28     TimeUnit.SECONDS.sleep(2);
    29 }

    3、 thenApply 方法

    当一个线程依赖另一个线程时,可以使用 thenApply 方法来把这两个线程串行化。 

    1 public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn)
    2 public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn)
    3 public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn, Executor executor)

     Function<? super T,? extends U>

    T:上一个任务返回结果的类型
    U:当前任务的返回值类型

    示例

     1 private static void thenApply() throws Exception {
     2     CompletableFuture<Long> future = CompletableFuture.supplyAsync(new Supplier<Long>() {
     3         @Override
     4         public Long get() {
     5             long result = new Random().nextInt(100);
     6             System.out.println("result1="+result);
     7             return result;
     8         }
     9     }).thenApply(new Function<Long, Long>() {
    10         @Override
    11         public Long apply(Long t) {
    12             long result = t*5;
    13             System.out.println("result2="+result);
    14             return result;
    15         }
    16     });
    17     
    18     long result = future.get();
    19     System.out.println(result);
    20 }

    4、 handle 方法

    handle 是执行任务完成时对结果的处理。
    handle 方法和 thenApply 方法处理方式基本一样。不同的是 handle 是在任务完成后再执行,还可以处理异常的任务。thenApply 只可以执行正常的任务,任务出现异常则不执行 thenApply 方法。

    1 public <U> CompletionStage<U> handle(BiFunction<? super T, Throwable, ? extends U> fn);
    2 public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn);
    3 public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn,Executor executor);

    示例

     1 public static void handle() throws Exception{
     2     CompletableFuture<Integer> future = CompletableFuture.supplyAsync(new Supplier<Integer>() {
     3 
     4         @Override
     5         public Integer get() {
     6             int i= 10/0;
     7             return new Random().nextInt(10);
     8         }
     9     }).handle(new BiFunction<Integer, Throwable, Integer>() {
    10         @Override
    11         public Integer apply(Integer param, Throwable throwable) {
    12             int result = -1;
    13             if(throwable==null){
    14                 result = param * 2;
    15             }else{
    16                 System.out.println(throwable.getMessage());
    17             }
    18             return result;
    19         }
    20      });
    21     System.out.println(future.get());
    22 }

    从示例中可以看出,在 handle 中可以根据任务是否有异常来进行做相应的后续处理操作。而 thenApply 方法,如果上个任务出现错误,则不会执行 thenApply 方法。

    5、 thenAccept 消费处理结果

    接收任务的处理结果,并消费处理,无返回结果。 

    1 public CompletionStage<Void> thenAccept(Consumer<? super T> action);
    2 public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action);
    3 public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action,Executor executor);

    示例

     1 public static void thenAccept() throws Exception{
     2     CompletableFuture<Void> future = CompletableFuture.supplyAsync(new Supplier<Integer>() {
     3         @Override
     4         public Integer get() {
     5             return new Random().nextInt(10);
     6         }
     7     }).thenAccept(integer -> {
     8         System.out.println(integer);
     9     });
    10     future.get();
    11 }

     从示例代码中可以看出,该方法只是消费执行完成的任务,并可以根据上面的任务返回的结果进行处理。并没有后续的输错操作。

    6、thenRun 方法

    跟 thenAccept 方法不一样的是,不关心任务的处理结果。只要上面的任务执行完成,就开始执行 thenAccept 。

    public CompletionStage<Void> thenRun(Runnable action);
    public CompletionStage<Void> thenRunAsync(Runnable action);
    public CompletionStage<Void> thenRunAsync(Runnable action,Executor executor);

    示例

    public static void thenRun() throws Exception{
        CompletableFuture<Void> future = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                return new Random().nextInt(10);
            }
        }).thenRun(() -> {
            System.out.println("thenRun ...");
        });
        future.get();
    }
    
    

    该方法同 thenAccept 方法类似。不同的是上个任务处理完成后,并不会把计算的结果传给 thenRun 方法。只是处理玩任务后,执行 thenAccept 的后续操作。

    7、thenCombine 合并任务

    thenCombine 会把 两个 CompletionStage 的任务都执行完成后,把两个任务的结果一块交给 thenCombine 来处理。

    1 public <U,V> CompletionStage<V> thenCombine(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn);
    2 public <U,V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn);
    3 public <U,V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn,Executor executor);

    示例

     1 private static void thenCombine() throws Exception {
     2     CompletableFuture<String> future1 = CompletableFuture.supplyAsync(new Supplier<String>() {
     3         @Override
     4         public String get() {
     5             return "hello";
     6         }
     7     });
     8     CompletableFuture<String> future2 = CompletableFuture.supplyAsync(new Supplier<String>() {
     9         @Override
    10         public String get() {
    11             return "hello";
    12         }
    13     });
    14     CompletableFuture<String> result = future1.thenCombine(future2, new BiFunction<String, String, String>() {
    15         @Override
    16         public String apply(String t, String u) {
    17             return t+" "+u;
    18         }
    19     });
    20     System.out.println(result.get());
    21 }

    8、thenAcceptBoth

    当两个CompletionStage都执行完成后,把结果一块交给thenAcceptBoth来进行消耗

    1 public <U> CompletionStage<Void> thenAcceptBoth(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action);
    2 public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action);
    3 public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action,     Executor executor);

    示例

     1 private static void thenAcceptBoth() throws Exception {
     2     CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
     3         @Override
     4         public Integer get() {
     5             int t = new Random().nextInt(3);
     6             try {
     7                 TimeUnit.SECONDS.sleep(t);
     8             } catch (InterruptedException e) {
     9                 e.printStackTrace();
    10             }
    11             System.out.println("f1="+t);
    12             return t;
    13         }
    14     });
    15         
    16     CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
    17         @Override
    18         public Integer get() {
    19             int t = new Random().nextInt(3);
    20             try {
    21                 TimeUnit.SECONDS.sleep(t);
    22             } catch (InterruptedException e) {
    23                 e.printStackTrace();
    24             }
    25             System.out.println("f2="+t);
    26             return t;
    27         }
    28     });
    29     f1.thenAcceptBoth(f2, new BiConsumer<Integer, Integer>() {
    30         @Override
    31         public void accept(Integer t, Integer u) {
    32             System.out.println("f1="+t+";f2="+u+";");
    33         }
    34     });
    35 }

    9、applyToEither 方法

    两个CompletionStage,谁执行返回的结果快,我就用那个CompletionStage的结果进行下一步的转化操作。

    1 public <U> CompletionStage<U> applyToEither(CompletionStage<? extends T> other,Function<? super T, U> fn);
    2 public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T, U> fn);
    3 public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T, U> fn,Executor executor);

    示例

     1 private static void applyToEither() throws Exception {
     2     CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
     3         @Override
     4         public Integer get() {
     5             int t = new Random().nextInt(3);
     6             try {
     7                 TimeUnit.SECONDS.sleep(t);
     8             } catch (InterruptedException e) {
     9                 e.printStackTrace();
    10             }
    11             System.out.println("f1="+t);
    12             return t;
    13         }
    14     });
    15     CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
    16         @Override
    17         public Integer get() {
    18             int t = new Random().nextInt(3);
    19             try {
    20                 TimeUnit.SECONDS.sleep(t);
    21             } catch (InterruptedException e) {
    22                 e.printStackTrace();
    23             }
    24             System.out.println("f2="+t);
    25             return t;
    26         }
    27     });
    28     
    29     CompletableFuture<Integer> result = f1.applyToEither(f2, new Function<Integer, Integer>() {
    30         @Override
    31         public Integer apply(Integer t) {
    32             System.out.println(t);
    33             return t * 2;
    34         }
    35     });
    36 
    37     System.out.println(result.get());
    38 }

    10、acceptEither 方法

    两个CompletionStage,谁执行返回的结果快,我就用那个CompletionStage的结果进行下一步的消耗操作。

    1 public CompletionStage<Void> acceptEither(CompletionStage<? extends T> other,Consumer<? super T> action);
    2 public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action);
    3 public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action,Executor executor);

    示例

    private static void acceptEither() throws Exception {
        CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                int t = new Random().nextInt(3);
                try {
                    TimeUnit.SECONDS.sleep(t);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("f1="+t);
                return t;
            }
        });
            
        CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                int t = new Random().nextInt(3);
                try {
                    TimeUnit.SECONDS.sleep(t);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("f2="+t);
                return t;
            }
        });
    f1.acceptEither(f2,
    new Consumer<Integer>() { @Override public void accept(Integer t) { System.out.println(t); } }); }

     11、runAfterEither 方法

    两个CompletionStage,任何一个完成了都会执行下一步的操作(Runnable)

    1 public CompletionStage<Void> runAfterEither(CompletionStage<?> other,Runnable action);
    2 public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action);
    3 public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action,Executor executor);

    示例

     1 private static void runAfterEither() throws Exception {
     2     CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
     3         @Override
     4         public Integer get() {
     5             int t = new Random().nextInt(3);
     6             try {
     7                 TimeUnit.SECONDS.sleep(t);
     8             } catch (InterruptedException e) {
     9                 e.printStackTrace();
    10             }
    11             System.out.println("f1="+t);
    12             return t;
    13         }
    14     });
    15         
    16     CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
    17         @Override
    18         public Integer get() {
    19             int t = new Random().nextInt(3);
    20             try {
    21                 TimeUnit.SECONDS.sleep(t);
    22             } catch (InterruptedException e) {
    23                 e.printStackTrace();
    24             }
    25             System.out.println("f2="+t);
    26             return t;
    27         }
    28     });
    29     f1.runAfterEither(f2, new Runnable() {
    30         
    31         @Override
    32         public void run() {
    33             System.out.println("上面有一个已经完成了。");
    34         }
    35     });
    36 }

    12、runAfterBoth

    两个CompletionStage,都完成了计算才会执行下一步的操作(Runnable)

    1 public CompletionStage<Void> runAfterBoth(CompletionStage<?> other,Runnable action);
    2 public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action);
    3 public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action,Executor executor);

    示例

     1 private static void runAfterBoth() throws Exception {
     2     CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
     3         @Override
     4         public Integer get() {
     5             int t = new Random().nextInt(3);
     6             try {
     7                 TimeUnit.SECONDS.sleep(t);
     8             } catch (InterruptedException e) {
     9                 e.printStackTrace();
    10             }
    11             System.out.println("f1="+t);
    12             return t;
    13         }
    14     });
    15         
    16     CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
    17         @Override
    18         public Integer get() {
    19             int t = new Random().nextInt(3);
    20             try {
    21                 TimeUnit.SECONDS.sleep(t);
    22             } catch (InterruptedException e) {
    23                 e.printStackTrace();
    24             }
    25             System.out.println("f2="+t);
    26             return t;
    27         }
    28     });
    29     f1.runAfterBoth(f2, new Runnable() {
    30         
    31         @Override
    32         public void run() {
    33             System.out.println("上面两个任务都执行完成了。");
    34         }
    35     });
    36 }

    13、thenCompose 方法

    thenCompose 方法允许你对两个 CompletionStage 进行流水线操作,第一个操作完成时,将其结果作为参数传递给第二个操作。

    1 public <U> CompletableFuture<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn);
    2 public <U> CompletableFuture<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn) ;
    3 public <U> CompletableFuture<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn, Executor executor) ;

    示例

     1 private static void thenCompose() throws Exception {
     2         CompletableFuture<Integer> f = CompletableFuture.supplyAsync(new Supplier<Integer>() {
     3             @Override
     4             public Integer get() {
     5                 int t = new Random().nextInt(3);
     6                 System.out.println("t1="+t);
     7                 return t;
     8             }
     9         }).thenCompose(new Function<Integer, CompletionStage<Integer>>() {
    10             @Override
    11             public CompletionStage<Integer> apply(Integer param) {
    12                 return CompletableFuture.supplyAsync(new Supplier<Integer>() {
    13                     @Override
    14                     public Integer get() {
    15                         int t = param *2;
    16                         System.out.println("t2="+t);
    17                         return t;
    18                     }
    19                 });
    20             }
    21             
    22         });
    23         System.out.println("thenCompose result : "+f.get());
    24     }
  • 相关阅读:
    [leetcode-671-Second Minimum Node In a Binary Tree]
    [leetcode-667-Beautiful Arrangement II]
    棋盘从左上到右下最小初始值
    [leetcode-666-Path Sum IV]
    [leetcode-665-Non-decreasing Array]
    [leetcode-215-Kth Largest Element in an Array]
    LINQ简记(3):子句
    技巧篇:如何重写基类的事件
    技巧篇:结合反射技术实现多算法动态加密
    龙年新作:水印文字添加工具源码摘要
  • 原文地址:https://www.cnblogs.com/jelly12345/p/14035195.html
Copyright © 2011-2022 走看看