一、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));});}