CompletableFuture详解

在阅读这篇文章之前,需要一点lambda知识,如果不太清楚的话,可以看我之前写的Java8中lambda详解

CompletableFuture的出现原因

我们上篇文章说了Future和FutureTask。但是Future有一个缺点,调用线程需要使用future.get()来获取调用结果,这个方法是阻塞的,也就说调用线程会被阻塞。

而CompeletableFuture提供了回调方法来解决这一问题。当任务执行完之后,会通知调用线程来执行回调方法。而在调用回调方法之前,调用线程可以执行其他任务,是非阻塞的。

除此之外,CompletableFuture还提供了串行、AND聚合、OR聚合调用多个任务,以及支持异常处理。

CompletableFuture中API

1、CompeletableFuture< Void > runAsync(Runnable r)
异步的执行Runnable,默认的会使用公共的ForkJoinPool

2、CompeletableFuture< Void > runAsync(Runnable r,Executor e)
和方法1的区别就是指定了线程池。

3、CompeletableFuture< U > supplyAsync(Supplier supplier)
异步的执行任务,和方法1不同的是Runnable没有返回值,而Supplier可以返回值。

4、CompeletableFuture< U > supplyAsync(Supplier supplier,Executor e)
和方法3不同的是,可以指定线程池

以上四个方法是异步执行任务。

CompletableFuture的串行调用

CompletableFuture提供了串行调用接口来保证两个CompletableFuture之间的串行调用,变相的可以实现回调方法的功能。

CompletableFuture提供了8个串行函数:
1、CompeletableFuture< U > thenApply(Function<T,R> f)
Function<T,R>需要传入参数,并且会返回值
2、CompeletableFuture< U > thenCompose(Function<T,R> f)
和thenApply不一样的是,传入的Function中代码需要包含CompletableFuture,需要传入参数,并且会返回值
3、CompeletableFuture< Void > thenAccept(Consumer< T > c)
Consumer需要传入参数,不会返回值 同步执行
4、CompeletableFuture< Void > thenRun(Runnable r)
Runnable既不能传入参数,也不能返回参数

5、CompeletableFuture< U > thenApplyAsync(Function<T,R> f)
6、CompeletableFuture< U > thenComposeAsync(Function<T,R> f)
7、CompeletableFuture< Void > thenAcceptAsync(Consumer< T > c)
8、CompeletableFuture< Void > thenRunAsync(Runnable r)

方法5-8的和方法1-4的区别,就是Async也就是会异步的调用后来的CompeletableFuture

CompletableFuture<String> f1 = CompletableFuture.supplyAsync(()->{
            System.out.println("this is f1");
            return "this is f1";
        });


        CompletableFuture<Integer> f2 = f1.thenApplyAsync((s)->{System.out.println(s+","+s);return 1;});

        CompletableFuture<Void> f3 = f1.thenAccept((s)->{System.out.println(s+"、"+s);});

        CompletableFuture<Void> f4 = f1.thenRun(()->System.out.println("runable"));

        CompletableFuture<String> f5 = f1.thenCompose(s->CompletableFuture.supplyAsync(()->{System.out.println(s);return "Compose";}));

在这里插入图片描述

从上述代码可以看出,f1.thenApplyAsync就是创建了一个CompletableFuture f2,其执行的任务就是

(s)->{System.out.println(s+","+s);return 1;}

f2是在f1执行之后调用的。

CompletableFuture的AND聚合调用

除了上面的前后调用关系外,CompletableFuture还提供了6种聚合调用方法,AND聚合调用的意思现在有三个CompletableFuture,只有当两个CompletableFuture都执行完后,才会执行第三个CompletableFuture。

1、CompletableFuture< U > thenCombine(Completable other,Function< T, R> f)
第三个CompletableFuture是Function类型的。
2、CompletableFuture< Void > runAfterBoth(Completable other,Runnable r)
第三个CompletableFuture是Runnable类型的。
3、CompletableFuture< Void > thenAcceptBoth(CompletableFuture other,Consumer c);
第三个CompletableFuture是Consumer类型的。

4、CompletableFuture< U > thenCombineAsync(Completable other,Function< T, R> f)
5、CompletableFuture< Void > runAfterBothAsync(Completable other,Runnable r)
6、CompletableFuture< Void > thenAcceptBothAsync(CompletableFuture other,Consumer c);
方法4-6相较于方法1-3的区别就是异步执行第三个CompletableFuture。

CompletableFuture<String> f1 = CompletableFuture.supplyAsync(()->{
    System.out.println("this is f1");
    return "f1 return";
});

CompletableFuture<String> f2 = CompletableFuture.supplyAsync(()->{
    System.out.println("this is f2");
    return "f2 return";
});
CompletableFuture<String> f6 = f1.thenCombine(f2,(s1,s2)->{System.out.println(s1+"--thenCombine--"+s2); return "this is f6";});

CompletableFuture<Void> f7 = f1.runAfterBoth(f2,()->{System.out.println("runnable");});

CompletableFuture<Void> f8 = f1.thenAcceptBoth(f2,(s1,s2)->{System.out.println(s1+"consumer"+s2);});

在这里插入图片描述

CompletableFuture的OR聚合调用

CompletableFuture提供了6个OR聚合调用。OR聚合调用的意思是,现在有三个CompletableFuture,当两个中的一个调用完成后,就会触发第三个CompletableFuture的执行。

1、CompletableFuture< U > applyToEither(CompletableFuture other,Function<T,R> f);
第三个CompletableFuture是Function类型的。
2、CompletableFuture< U > acceptEither(CompletableFuture other,Consumer< T > c);
第三个CompletableFuture是Consumer类型的。
3、CompletableFuture< U > runAfterEither(CompletableFuture other,Runnable r);
第三个CompletableFuture是Runnable类型的。

4、CompletableFuture< U > applyToEitherAsync(CompletableFuture other,Function<T,R> f);
5、CompletableFuture< U > acceptEitherAsync(CompletableFuture other,Consumer< T > c);
6、CompletableFuture< U > runAfterEitherAsync(CompletableFuture other,Runnable r);

方法4-6相较于方法1-3的区别就是异步执行第三个CompletableFuture。

CompletableFuture<String> f1 = CompletableFuture.supplyAsync(()->{
    try {
        Thread.sleep(4000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("this is f1");
    return "f1 return";
});

CompletableFuture<String> f2 = CompletableFuture.supplyAsync(()->{
    System.out.println("this is f2");
    return "f2 return";
});

CompletableFuture<String> f9 = f1.applyToEither(f2,(s1)->{System.out.println(s1+"--applyToEither--");return s1+"**";});

CompletableFuture<Void> f10 = f1.acceptEither(f2,(s1)->{System.out.println(s1+"--accept--");});

 CompletableFuture<Void> f11 = f1.runAfterEither(f2,()->{System.out.println("Runnable");});

 f1.join();

在这里插入图片描述

CompletableFuture中异常处理

CompletableFuture也提供了catch finally的机制
1、Catch
CompletableFuture< R > exceptionally(Function<T,R> f)
当发生异常的时候,会调用f。
2、finally
CompletableFuture< R > whenComplete(BiConsumer< T > c)
只接收参数
CompletableFuture< R > handler(BiFunction<T,R> f)
既接收参数,又返回值

对于whenComplete、handler都有对应的异步调用方法,对应方法为whenCompleteAsync()、handlerAsync()。

CompletableFuture<String> f1 = CompletableFuture.supplyAsync(()->{

    System.out.println("this is f1");
    int a = 0/0;
    return "f1 return";
});
f1.exceptionally(e->{e.printStackTrace();return e.toString();});
f1.whenComplete((r1,r2)->{System.out.println("complete-----"+r1+"-----"+r2);});
f1.handle((r1,r2)->{System.out.println("handle-----"+r1+"-----"+r2);return r1 +"--"+r2;});

在这里插入图片描述

总结

CompletableFuture相较于Future,支持任务之间的串行调用、AND聚合调用、OR聚合调用、异常处理等功能。串行调用可以实现回调函数。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值