使用Future获得异步执行结果时,要么调用阻塞方法get(),要么轮询看isDone()是否为true,这两种方法都不是很好,因为主线程也会被迫等待。
从Java 8开始引入了CompletableFuture,它针对Future做了改进,可以传入回调对象,当异步任务完成或者发生异常时,自动调用回调对象的回调方法。
看看如何使用CompletableFuture:
CompletableFuture的使用
public static void main(String[] args) throws ExecutionException, InterruptedException {
//同步,异步,异步回调
//MQ消息中除间件
//消息中间件:实现解偶
//同步
//Void 对象代表返回对象为空
CompletableFuture<Void> future1=CompletableFuture.runAsync(()->{
try {
Thread.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("CompletableFuture.runAsync");
return;
});
//异步回调
CompletableFuture<Integer> future2=CompletableFuture.supplyAsync(()->{
System.out.println("CompletableFuture.supplyAsync");
int a =10/0;
return 1024;
});
future2.whenComplete((t,u)->{
System.out.println(t+"--t");//t-1024 异步回调的计算结果
System.out.println(u+"--u");//u-null u是错误信息,当报错的时候u就会有值
}).exceptionally(f->{
System.out.println(f.getMessage());
return 444;
});
future1.get();
}
上面我们一不需要传入Supplier接口的对象,我们使用了lambda简化了直接写了;
可以看到相比于Future:
- 异步任务结束时,会自动回调某个对象的方法;
- 异步任务出错时,会自动回调某个对象的方法;
- 主线程设置好回调后,不再关心异步任务的执行。
同时CompletableFuture还有个强大的功能就是可以多个CompletableFuture串行执行:
//异步串行
CompletableFuture<Integer> future1=CompletableFuture.supplyAsync(()->{
System.out.println("异步1执行");
// int a =10/0;
return 1024;
});
CompletableFuture<Integer> future2= future1.thenApplyAsync((preReturn)->{
System.out.println("2执行:上一步返回的是:"+preReturn);
return 2048;
});
// future2.thenApply((result)->{
// System.out.println("result:"+result);
// return null;
// });
future2.whenComplete((t,u)->{
System.out.println(t+"--t");//t-2048 异步回调的计算结果
System.out.println(u+"--u");//u-null u是错误信息,当报错的时候u就会有值
}).exceptionally(f->{
System.out.println(f.getMessage());
return 444;
});
Thread.sleep(3000);
这里需要注意的是 主线程不要立刻结束,否则CompletableFuture默认使用的线程池会立刻关闭:
与Future相比:
Future获取异步执行结果,要么调用阻塞方法get(),要么轮询看isDone()是否为true,这两种方法都不是很好,因为主线程也会被迫等待;
而CompletableFuture:
- 异步任务结束时,会自动回调某个对象的方法;
- 异步任务出错时,会自动回调某个对象的方法;
- 主线程设置好回调后,不再关心异步任务的执行。