原文网址:Java异步--CompletableFuture--实例_IT利刃出鞘的博客-CSDN博客
简介
说明
本文介绍CompletableFuture这个异步编程API。
JDK8新加CompletableFuture,实现了Future<T>, CompletionStage<T>两个接口。
其位置:java.util.concurrent.CompletableFuture;
Future与CompletableFuture对比
Future与CompletableFuture相比,主要缺点如下(下边这些功能CompletableFuture都有):
- 不支持手动完成
- 我提交了一个任务,但是执行太慢了,我通过其他路径已经获取到了任务结果,现在没法把这个任务结果,通知到正在执行的线程,所以必须主动取消或者一直等待它执行完成。
- 不支持回调函数
- 无法在获取任务之后执行额外的任务。因为Future的get方法会一直阻塞到任务完成,Future不支持回调函数,所以无法实现这个功能。
- 不支持链式调用
- 对于Future的执行结果,我们想继续传到下一个Future处理使用,从而形成一个链式的pipline调用,这在Future中是没法实现的。
- 不支持多个Future合并
- 比如我们有10个Future并行执行,我们想在所有的Future运行完毕之后,执行某些函数,是没法通过Future实现的。
- 不支持异常处理
- Future的API没有任何的异常处理的api,所以在异步运行时,如果出了问题是不好定位的。
与函数式接口的关系
CompletableFuture的方法名称与函数式接口有很大的关系,所以此处特地列出来。
接口定义 | 方法 | 说明 |
Runnable | void run(); | 参数:无。返回值:无。 |
Function< T, R > | R apply(T t); | 参数:T对象。返回值:R对象。 |
Consumer< T > | void accept(T t); | 参数:T对象。返回值:无 |
Supplier< T > | T get(); | 参数:无。返回值:T对象 |
BiConsumer<T, U> | void accept(T t, U u); | 参数:T对象。返回值:boolean |
创建
简介
CompletableFuture提供了如下四个静态方法来创建一个异步操作。
public static CompletableFuture<Void> runAsync(Runnable runnable)
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)
- runAsync:不支持返回值。因为它接收Runnable接口,Runnable是没有返回值的。
- supplyAsync:支持返回值。因为它接收Supplier接口,Supplier是有返回值的。
- 若executor参数没有设置值,那么会使用ForkJoinPool.commonPool默认线程池执行任务。实际业务中我们是严谨手动创建线程的。
- ForkJoinPool 的线程数默认是 CPU 的核心数。但是,不要所有业务共用一个线程池,因为,一旦有任务执行一些很慢的 I/O 操作,就会导致线程池中所有线程都阻塞在 I/O 操作上,从而造成线程饥饿,进而影响整个系统的性能。
实例(无Executor)
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> System.out.println("runAsync"));
future.get();
执行结果:
runAsync
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
System.out.println("supplyAsync");
return "supplyAsync的返回值";
});
System.out.println(future.get());
执行结果:
supplyAsync
supplyAsync的返回值
CompletableFuture.runAsync(() -> {
System.out.println(Thread.currentThread().getName() + " 执行异步任务 runAsync");
});
String result = CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread().getName() + " 执行异步任务 supplyAsync");
return "supplyAsync的返回值";
}).get();
System.out.println(result);
上边是文章的部分内容,为便于维护,全文已迁移到此网址:Java异步-CompletableFuture-实例 - 自学精灵