type
status
date
slug
summary
tags
category
icon
password
Property
使用
Future
获得异步执行结果时,要么调用阻塞方法get()
,要么轮询看isDone()
是否为true
,这两种方法都不是很好,因为主线程也会被迫等待。从Java 8开始引入了
CompletableFuture
,它针对Future
做了改进,可以传入回调对象,当异步任务完成或者发生异常时,自动调用回调对象的回调方法。我们以获取股票价格为例,看看如何使用
CompletableFuture
:创建一个
CompletableFuture
是通过CompletableFuture.supplyAsync()
实现的,它需要一个实现了Supplier
接口的对象:这里我们用lambda语法简化了一下,直接传入
Main::fetchPrice
,因为Main.fetchPrice()
静态方法的签名符合Supplier
接口的定义(除了方法名外)。紧接着,
CompletableFuture
已经被提交给默认的线程池执行了,我们需要定义的是CompletableFuture
完成时和异常时需要回调的实例。完成时,CompletableFuture
会调用Consumer
对象:异常时,
CompletableFuture
会调用Function
对象:这里我们都用lambda语法简化了代码。
可见
CompletableFuture
的优点是:- 异步任务结束时,会自动回调某个对象的方法;
- 异步任务出错时,会自动回调某个对象的方法;
- 主线程设置好回调后,不再关心异步任务的执行。
如果只是实现了异步回调机制,我们还看不出
CompletableFuture
相比Future
的优势。CompletableFuture
更强大的功能是,多个CompletableFuture
可以串行执行,例如,定义两个CompletableFuture
,第一个CompletableFuture
根据证券名称查询证券代码,第二个CompletableFuture
根据证券代码查询证券价格,这两个CompletableFuture
实现串行操作如下:除了串行执行外,多个
CompletableFuture
还可以并行执行。例如,我们考虑这样的场景:同时从新浪和网易查询证券代码,只要任意一个返回结果,就进行下一步查询价格,查询价格也同时从新浪和网易查询,只要任意一个返回结果,就完成操作:
上述逻辑实现的异步查询规则实际上是:
除了
anyOf()
可以实现“任意个CompletableFuture
只要一个成功”,allOf()
可以实现“所有CompletableFuture
都必须成功”,这些组合操作可以实现非常复杂的异步流程控制。最后我们注意
CompletableFuture
的命名规则:xxx()
:表示该方法将继续在已有的线程中执行;
xxxAsync()
:表示将异步在线程池中执行。
小结
CompletableFuture
可以指定异步处理流程:thenAccept()
处理正常结果;
exceptional()
处理异常结果;
thenApplyAsync()
用于串行化另一个CompletableFuture
;
anyOf()
和allOf()
用于并行化多个CompletableFuture
。