JAVA8新特性 异步_Java8 新特性CompletableFuture-异步编程

CompletableFuture,增强Future

Future 接口介绍

​ Java5 新增了 Future 接口,用于描述一个异步计算的结果。虽然 Future 以及相关使用方法提供了异步执行任务的能力,但是对于结果的获取却是很不方便,只能通过阻塞或者轮询的方式得到任务的结果。阻塞的方式显然和我们的异步编程的初衷相违背,轮询的方式又会耗费无谓的 CPU 资源,而且也不能及时地得到计算结果,为什么不能用观察者设计模式呢?即当计算结果完成及时通知监听者(回调)。

​ Future存在的一些短板

不能手动完成计算

调用 get() 方法会阻塞程序

不能链式执行

整合多个 Future 执行结果方式笨重

没有好的异常处理方案

CompletableFuture介绍

​ Java 8 中, 新增加了一个包含 50 个方法左右的类–CompletableFuture,它提供了非常强大的 Future 的扩展功能,可以帮助我们简化异步编程的复杂性,并且提供了函数式编程的能力,可以通过回调的方式处理计算结果,也提供了转换和组合 CompletableFuture 的方法。

bec0c4873f24

CompletableFuture类结构

实现了 Future 接口

实现了 Future 接口,那就具有 Future 接口的相关特性

实现了 CompletionStage 接口

CompletionStage 接口实际上提供了同步或异步运行计算的舞台,所以我们可以通过实现多个 CompletionStage 命令,并且将这些命令串联在一起的方式实现多个命令之间的触发。

bec0c4873f24

CompletionStage 方法清单

带有then通常是串行的表现

带有combine或者and 通常是聚合and

带有Either 通常是聚合or

带有handle或者exceptionally通常用来处理异常

快速开始

1. 创建实例

CompletableFuture completableFuture = new CompletableFuture<>();

System.out.println(completableFuture.get());

这个时候会发现,程序会一直处于阻塞状态,因为get()方法在任务结束之前将一直处在阻塞状态。这时需要我们调用complete()方法去手动完成。

CompletableFuture completableFuture = new CompletableFuture<>();

completableFuture.complete("hello");

System.out.println(completableFuture.get());

2. runAsync

静态方法。使用runAsnc进行一次异步计算

CompletableFuture hello = CompletableFuture.runAsync(() -> System.out.println("运行在一个单独的线程当中"));

hello.get();

runAsync里面传入的runnable是异步去执行,当我们没有传入Executor时,它会使用默认的连接池。

3. supplyAsync

静态方法。supplyAsync 是带有返回值的

CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> "hello");

System.out.println(completableFuture.get()); //hello

4. thenAccept

执行thenAccept之后,get()就不会再返回数据了

CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> "hello")

.thenAccept(System.out::println);

System.out.println(completableFuture.get()); // null

5. thenApply

可使用thenApply方法转换CompletableFuture对象的值,有点像使用Stream的map方法。

CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> {

sleep3s();

return "hello";

})

.thenApply(e -> e + " world")

.thenAccept(System.out::println);

completableFuture.join();

get() 和 join()的区别在于,抛出异常不同,join不强制你去处理异常。

6. thenCompose

thenCompose 的功能类似stream的flatMap,转换CompletableFuture,与thenApply不同的是,thenCompose接收的Function参数返回值必须是CompletionStage的实现类,更多用于连接CompletableFuture

public static void main(String[] args) {

CompletableFuture userIdFuture = getUserId("5466685299237");

CompletableFuture deptFuture = userIdFuture.thenCompose(Demo6::getDept);

System.out.println(deptFuture.join()); // 研发部

}

// 获取用户ID

static CompletableFuture getUserId(String code) {

return CompletableFuture.supplyAsync(() -> "10086");

}

// 获取用户所在部门信息

static CompletableFuture getDept(String userId) {

return CompletableFuture.supplyAsync(() -> "研发部");

}

7. thenCombine

聚合两个CompletableFuture

CompletableFuture helloFuture = CompletableFuture.supplyAsync(() -> "hello");

CompletableFuture worldFuture = CompletableFuture.supplyAsync(() -> "world");

helloFuture.thenCombine(worldFuture, (e1, e2)-> e1.toUpperCase() +" "+ e2.toUpperCase() + "!")

.thenAccept(System.out::println)

.join(); //HELLO WORLD!

8. allOf | anyOf

静态方法。顾名思义,allOf 所有都完成,anyOf只有有任意一个完成。

CompletableFuture task1 = CompletableFuture.supplyAsync(() -> {

sleep(3);

System.out.println("task1-完成");

return "task1";

});

CompletableFuture task2 = CompletableFuture.supplyAsync(() -> {

sleep(1);

System.out.println("task2-完成");

return "task3";

});

CompletableFuture task3 = CompletableFuture.supplyAsync(() -> {

System.out.println("task3-完成");

return "task3";

});

CompletableFuture.allOf(task1, task2, task3)

.thenAccept(e-> System.out.println("全部完成"))

.join();

上面代码如果换成anyOf,那么只要有一个完成,就会来到thenAccept

9. exceptionally

exceptionally 就相当于 catch,出现异常,将会跳过 thenApply 的后续操作,直接捕获异常,进行一场处理

int i = 1;

CompletableFuture exceptionally = CompletableFuture.supplyAsync(() -> {

if (i == 1)

throw new RuntimeException("异常啦~");

return "hello";

}).thenApply(e -> e.toUpperCase())

.exceptionally(ex -> "error");

System.out.println(exceptionally.join()); // error

10. handle

handle,的处理类似try...finally, 不管有没有发生异常都会来到handle。handle接收两个参数,一个正常的返回值,一个是异常。

int i = 1;

CompletableFuture exceptionally = CompletableFuture.supplyAsync(() -> {

if (i == 1)

throw new RuntimeException("异常啦~");

return "hello";

}).thenApply(e -> e.toUpperCase())

.handle((res, ex)-> {

return res;

});

System.out.println(exceptionally.join()); // null

总结

CompletableFuture给并发编程带来了新的体验,函数式编程,并行,聚合,异常等操作降低了并发编程难度。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值