Java8-02-CompletableFuture续

1-两个任务组合,都要完成

* thenCombine:两个任务都要完成,组合两个future,获取两个future的返回结果,并返回当前任务的返回值

public <U,V> CompletableFuture<V> thenCombine(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn)

public <U,V> CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn)

public <U,V> CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn, Executor executor)

 public static void main10() throws Exception {
        System.out.println("main start....");


        CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {

            }
            int i = 100 / 10;
            System.out.println("运行结果:" + i + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            return i;
        }, executorService);

        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程2:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            String result="hello";
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {

            }
            System.out.println("运行结果:" + result+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            return result;
        }, executorService);

        CompletableFuture<String> completableFuture = future01.thenCombineAsync(future02, (res1, res2) -> {
            System.out.println("当前线程3:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            System.out.println("任务1结果:" + res1 + "---->任务2结果:" + res2);
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {

            }
            return res1 + res2;
        }, executorService);
        System.out.println("最后返回结果:"+completableFuture.get()+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        System.out.println("main end....");

    }

/**

* thenCombineAsync

* <p>

* 输出结果:

main start....

当前线程1:13->当前时间:2021-10-18 11:40:12

当前线程2:14->当前时间:2021-10-18 11:40:12

运行结果:hello->当前时间:2021-10-18 11:40:14

运行结果:10->当前时间:2021-10-18 11:40:16

当前线程3:15->当前时间:2021-10-18 11:40:16

任务1结果:10---->任务2结果:hello

最后返回结果:10hello->当前时间:2021-10-18 11:40:19

main end....

*/

* thenAcceptBoth:两个任务都要完成,组合两个future,获取两个future的返回结果,然后处理任务,没有返回值

public <U> CompletableFuture<Void> thenAcceptBoth(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action)

public <U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action)

public <U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action, Executor executor)

public static void main11() throws Exception {
        System.out.println("main start....");


        CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {

            }
            int i = 100 / 10;
            System.out.println("运行结果:" + i + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            return i;
        }, executorService);

        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程2:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            String result="hello";
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {

            }
            System.out.println("运行结果:" + result+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            return result;
        }, executorService);

        CompletableFuture<Void> completableFuture = future01.thenAcceptBothAsync(future02, (res1, res2) -> {
            System.out.println("当前线程3:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            System.out.println("任务1结果:" + res1 + "---->任务2结果:" + res2);
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
            }
            System.out.println("任务1结果:" + res1 + "---->任务2结果:" + res2 + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        }, executorService);
        System.out.println("最后返回结果:"+completableFuture.get()+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        System.out.println("main end....");

    }

/**

* thenAcceptBoth

* <p>

* 输出结果:

main start....

当前线程2:14->当前时间:2021-10-18 11:46:03

当前线程1:13->当前时间:2021-10-18 11:46:03

运行结果:hello->当前时间:2021-10-18 11:46:05

运行结果:10->当前时间:2021-10-18 11:46:07

当前线程3:15->当前时间:2021-10-18 11:46:07

任务1结果:10---->任务2结果:hello

任务1结果:10---->任务2结果:hello->当前时间:2021-10-18 11:46:10

最后返回结果:null->当前时间:2021-10-18 11:46:10

main end....

*/

*runAfterBoth:两个任务都要完成,组合两个future,不需要获取两个future的返回结果,只需要两个future完成任务后,处理该任务

public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other,Runnable action)

public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action)

public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action,Executor executor)

 public static void main12() throws Exception {
        System.out.println("main start....");


        CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {

            }
            int i = 100 / 10;
            System.out.println("运行结果:" + i + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            return i;
        }, executorService);

        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程2:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            String result="hello";
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {

            }
            System.out.println("运行结果:" + result+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            return result;
        }, executorService);

        CompletableFuture<Void> completableFuture = future01.runAfterBothAsync(future02, () -> {
            System.out.println("当前线程3:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            System.out.println("不需要两个future的结果,自己执行");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
            }
            System.out.println("不需要两个future的结果,自己执行"+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        }, executorService);
        System.out.println("最后返回结果:"+completableFuture.get()+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        System.out.println("main end....");

    }

/**

* runAfterBothAsync

* <p>

* 输出结果:

main start....

当前线程1:13->当前时间:2021-10-18 11:48:27

当前线程2:14->当前时间:2021-10-18 11:48:27

运行结果:hello->当前时间:2021-10-18 11:48:29

运行结果:10->当前时间:2021-10-18 11:48:31

当前线程3:15->当前时间:2021-10-18 11:48:31

不需要两个future的结果,自己执行

不需要两个future的结果,自己执行->当前时间:2021-10-18 11:48:34

最后返回结果:null->当前时间:2021-10-18 11:48:34

main end....

*/

2-两个任务组合:一个完成

public <U> CompletableFuture<U> applyToEither(CompletionStage<? extends T> other, Function<? super T, U> fn)

public <U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn)

public <U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn,Executor executor)

public static void main13() throws Exception {
        System.out.println("main start....");
        CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {

            }
            int i = 100 / 10;
            System.out.println("运行结果:" + i + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            return i;
        }, executorService);

        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程2:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            String result="hello";
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {

            }
            System.out.println("运行结果:" + result+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            return result;
        }, executorService);

        CompletableFuture<String> completableFuture = future01.applyToEitherAsync(future02, (res) -> {
            System.out.println("当前线程3:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            //这里两个future返回值类型必须一致,否则不知道用哪个
            System.out.println("两个future的任意一个的结果,res=" + res);
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
            }
            System.out.println("两个future的任意一个的结果,res=" + res + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            return "world:" + res;
        }, executorService);
        System.out.println("最后返回结果:"+completableFuture.get()+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        System.out.println("main end....");

    }

* applyToEitherAsync

* <p>

* 输出结果:

main start....

当前线程2:14->当前时间:2021-10-18 13:49:38

当前线程1:13->当前时间:2021-10-18 13:49:38

运行结果:hello->当前时间:2021-10-18 13:49:40

当前线程3:15->当前时间:2021-10-18 13:49:40

两个future的任意一个的结果,res=hello

运行结果:10->当前时间:2021-10-18 13:49:42

两个future的任意一个的结果,res=hello->当前时间:2021-10-18 13:49:43

最后返回结果:world:hello->当前时间:2021-10-18 13:49:43

main end....

public CompletableFuture<Void> acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action)

public CompletableFuture<Void> acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action)

public CompletableFuture<Void> acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action,Executor executor)

public CompletableFuture<Void> runAfterEither(CompletionStage<?> other,Runnable action)

public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action)

public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action,Executor executor)

3-多任务组合

*allOf:等待所有任务完成

*anyOf:只要有一个任务完成

public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)

public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)

ps:allOf方法使用场景:比如电商系统中商品详情页,三个查询:查询商品图片,查询商品属性,查询商品描述;可以分解三个查询,同时查询,最后等待三个查询完成得到结果

public static void main14() throws Exception {
        System.out.println("main start....");
        CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {

            }
            int i = 100 / 10;
            System.out.println("运行结果:" + i + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            return i;
        }, executorService);

        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程2:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            String result="hello";
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {

            }
            System.out.println("运行结果:" + result+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            return result;
        }, executorService);

        CompletableFuture<Void> completableFuture = CompletableFuture.allOf(future01,future02);
        completableFuture.get();
        System.out.println("最后返回结果"+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        System.out.println("main end....");

    }

/**

*

* <p>

* 输出结果:

*

main start....

当前线程1:13->当前时间:2021-10-18 14:18:38

当前线程2:14->当前时间:2021-10-18 14:18:38

运行结果:hello->当前时间:2021-10-18 14:18:40

运行结果:10->当前时间:2021-10-18 14:18:42

最后返回结果->当前时间:2021-10-18 14:18:42

main end....

*/

4-CompletionService

CompletionService的实现原理是内部维护了一个阻塞队列,当任务执行结束就把任务的执行结果加入到阻塞队列中。

 public static void main16() throws Exception {
        System.out.println("main start...."+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        CompletionService<String> completionService = new ExecutorCompletionService<>(executorService);
        for(int i=1;i<=3;i++){
            final int j=i;
            completionService.submit(() -> {
                System.out.println("线程:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"第几次:"+j);
                String shopInfo = getShopInfo(j);
                return shopInfo;
            });
        }
        for(int i=1;i<=3;i++){
            try{
                System.out.println( "执行->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                String res = completionService.take().get(6L,TimeUnit.SECONDS);
                System.out.println("获取结果线程:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"第几次:"+i+"获取值为:"+res);
            }catch(Exception e){
                System.out.println("获取结果线程error:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"第几次:"+i+"获取值为000");
            }
        }
        System.out.println("main end...."+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    }


public static String getShopInfo(int i) throws Exception{
        if(i==1){
            TimeUnit.SECONDS.sleep(5);
            return "A";
        }
        if(i==2){
            TimeUnit.SECONDS.sleep(8);
            int aa=10/0;
            return "B";
        }
        if(i==3){
            TimeUnit.SECONDS.sleep(4);
            return "C";
        }
        return "D";
    }

/**

* CompletionService 应用场景

* 比如我们平台【医药平台】 需要去每个药店A.B.C查询结果,

* 如果串行化,比如A药店需要5秒;B药店需要8秒;C药店需要4秒,那么系统一共5+8+4=17秒

* 如果并行化,那么最多就是8秒;

*

* 如果我们进一步优化,比如要求7秒内有结果,还可以设置获取值是7秒时间【通过http请求设置超时时间】,丢弃B药店8秒

*

*

*main start....->当前时间:2021-10-18 14:49:13

* 执行->当前时间:2021-10-18 14:49:13

* 线程:13->当前时间:2021-10-18 14:49:13第几次:1

* 线程:15->当前时间:2021-10-18 14:49:13第几次:3

* 线程:14->当前时间:2021-10-18 14:49:13第几次:2

* 获取结果线程:1->当前时间:2021-10-18 14:49:17第几次:1获取值为:C

* 执行->当前时间:2021-10-18 14:49:17

* 获取结果线程:1->当前时间:2021-10-18 14:49:18第几次:2获取值为:A

* 执行->当前时间:2021-10-18 14:49:18

* 获取结果线程error:1->当前时间:2021-10-18 14:49:21第几次:3获取值为000

* main end....->当前时间:2021-10-18 14:49:21

*

*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值