CompleteableFuture异步编程框架
一、CompleteableFuture
CompleteableFuture是Java 8中的一个类,它提供了一种异步编程的方式。使用CompleteableFuture可以提高程序的并发性和性能。
二、案例引出
2.1 案例代码
-
目录结构
-
有3个被调用的service(MemberService,OrderService,ProductService),每个service中有个search方法,分别耗时5,4,3秒钟。
-
测试代码,需要计算查询需求的总体耗时
2.2 引出CompleteableFuture异步调用
有一个查询需求,需要分别调用这3个service的search方法,获取对应会员、订单、产品列表。这3个调用的返回结果之间没有依赖关系。
- 串行调用
public void query1(){
List<Member> members = memberService.search();
List<Order> orders = orderService.search();
List<Product> products = productService.search();
}
耗时为3+4+5=12秒
- 并行调用–也就是异步调用
public void query2() throws ExecutionException, InterruptedException {
CompletableFuture<List<Member>> memberFuture = CompletableFuture.supplyAsync(() -> memberService.search());
CompletableFuture<List<Order>> orderFuture = CompletableFuture.supplyAsync(() -> orderService.search());
CompletableFuture<List<Product>> productFuture = CompletableFuture.supplyAsync(() -> productService.search());
CompletableFuture.allOf(memberFuture,orderFuture,productFuture).get();
}
耗时为max{5,4,3}=5秒
三、CompletableFuture常用方法
1. supplyAsync( )
开启一个异步调用,并返回一个CompletableFuture对象
public void query2(){
CompletableFuture<List<Member>> memberFuture = CompletableFuture.supplyAsync(() -> memberService.search());
CompletableFuture<List<Order>> orderFuture = CompletableFuture.supplyAsync(() -> orderService.search());
CompletableFuture<List<Product>> productFuture = CompletableFuture.supplyAsync(() -> productService.search());
}
2. runAsync( )
public void query2(){
CompletableFuture.runAsync(() -> memberService.search());
CompletableFuture.runAsync(() -> orderService.search());
CompletableFuture.runAsync(() -> productService.search());
}
3. get( )
阻塞式地获取一个CompletableFuture对象的结果,抛出ExecutionException, InterruptedException异常
public void query2() throws ExecutionException, InterruptedException {
CompletableFuture<List<Member>> memberFuture = CompletableFuture.supplyAsync(() -> memberService.search());
List<Member> members = memberFuture.get();
}
4.链式调用–thenApply( )
返回的结果如果是CompletableFuture,可以继续调用相关api
thenApply( )方法:前面任务执行完后执行当前任务。消费上一次调用的结果,返回另一个结果
public void query2() throws ExecutionException, InterruptedException {
CompletableFuture<List<Order>> future = CompletableFuture.supplyAsync(() -> memberService.search())
.thenApply(lastResult -> orderService.search());
List<Order> orders = future.get();
}
5. thenRun( )
前面任务执行完后执行当前任务。不管上一次调用的结果是什么,没有参数,没有返回值
public void query2() throws ExecutionException, InterruptedException {
CompletableFuture.supplyAsync(() -> memberService.search())
.thenRun(() -> orderService.search());
}
6. thenAccept( )
前面任务执行完后执行当前任务。消费上一次调用的结果,没有返回值
public void query2() throws ExecutionException, InterruptedException {
CompletableFuture.supplyAsync(() -> memberService.search())
.thenAccept(lastResult -> orderService.search());
}
7. anyOf( )
将多个future对象合并,返回最早运行结束的对象
public void query2() throws ExecutionException, InterruptedException {
CompletableFuture<List<Member>> memberFuture = CompletableFuture.supplyAsync(() -> memberService.search());
CompletableFuture<List<Order>> orderFuture = CompletableFuture.supplyAsync(() -> orderService.search());
CompletableFuture<List<Product>> productFuture = CompletableFuture.supplyAsync(() -> productService.search());
CompletableFuture<Object> future = CompletableFuture.anyOf(memberFuture, orderFuture, productFuture);
System.out.println(future.get());
}
8. allOf( )
等待所有并行任务执行后,再执行后面的操作。
allOf( ):返回CompletableFuture<Void>对象,本身并不会阻塞
示例:等待memberService和orderService都结束后,再执行后面的异步操作。
public void query2(){
long a = System.currentTimeMillis();
CompletableFuture<List<Member>> memberFuture = CompletableFuture.supplyAsync(() -> memberService.search());
CompletableFuture<List<Order>> orderFuture = CompletableFuture.supplyAsync(() -> orderService.search());
CompletableFuture<Void> allFutures = CompletableFuture.allOf(memberFuture, orderFuture);
allFutures.thenRun(()->{
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
long b = System.currentTimeMillis();
System.out.println("耗时111:"+(b-a));
});
}