前言
以前需要异步执行一个任务时,一般是用Thread或者线程池Executor去创建。如果需要返回值,则是调用Executor.submit获取Future。但是多个线程存在依赖组合,我们又能怎么办?可使用同步组件CountDownLatch、CyclicBarrier等;其实有简单的方法,就是用CompeletableFuture
- 线程任务的创建
 - 线程任务的串行执行
 - 线程任务的并行执行
 - 处理任务结果和异常
 - 多任务的简单组合
 - 取消执行线程任务
 - 任务结果的获取和完成与否判断
 
关注公众号,一起交流,微信搜一搜: 潜行前行
1 创建异步线程任务
根据supplier创建CompletableFuture任务
1  | java复制代码//使用内置线程ForkJoinPool.commonPool(),根据supplier构建执行任务  | 
根据runnable创建CompletableFuture任务
1  | java复制代码//使用内置线程ForkJoinPool.commonPool(),根据runnable构建执行任务  | 
- 使用示例
 
1  | java复制代码ExecutorService executor = Executors.newSingleThreadExecutor();  | 
常量值作为CompletableFuture返回
1  | java复制代码//有时候是需要构建一个常量的CompletableFuture  | 
2 线程串行执行
任务完成则运行action,不关心上一个任务的结果,无返回值
1  | java复制代码public CompletableFuture<Void> thenRun(Runnable action)  | 
- 使用示例
 
1  | java复制代码CompletableFuture<Void> future = CompletableFuture  | 
任务完成则运行action,依赖上一个任务的结果,无返回值
1  | java复制代码public CompletableFuture<Void> thenAccept(Consumer<? super T> action)  | 
- 使用示例
 
1  | java复制代码ExecutorService executor = Executors.newSingleThreadExecutor();  | 
任务完成则运行fn,依赖上一个任务的结果,有返回值
1  | java复制代码public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn)  | 
- 使用示例
 
1  | java复制代码ExecutorService executor = Executors.newSingleThreadExecutor();  | 
thenCompose - 任务完成则运行fn,依赖上一个任务的结果,有返回值
- 类似thenApply(区别是thenCompose的返回值是CompletionStage,thenApply则是返回 U),提供该方法为了和其他CompletableFuture任务更好地配套组合使用
 
1  | java复制代码public <U> CompletableFuture<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn)  | 
- 使用示例
 
1  | java复制代码//第一个异步任务,常量任务  | 
3 线程并行执行
两个CompletableFuture并行执行完,然后执行action,不依赖上两个任务的结果,无返回值
1  | java复制代码public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other, Runnable action)  | 
- 使用示例
 
1  | java复制代码//第一个异步任务,常量任务  | 
两个CompletableFuture并行执行完,然后执行action,依赖上两个任务的结果,无返回值
1  | java复制代码//调用方任务和other并行完成后执行action,action再依赖消费两个任务的结果,无返回值  | 
- 使用示例
 
1  | java复制代码//第一个异步任务,常量任务  | 
两个CompletableFuture并行执行完,然后执行fn,依赖上两个任务的结果,有返回值
1  | java复制代码//调用方任务和other并行完成后,执行fn,fn再依赖消费两个任务的结果,有返回值  | 
- 使用示例
 
1  | java复制代码//第一个异步任务,常量任务  | 
4 线程并行执行,谁先执行完则谁触发下一任务(二者选其最快)
上一个任务或者other任务完成, 运行action,不依赖前一任务的结果,无返回值
1  | java复制代码public CompletableFuture<Void> runAfterEither(CompletionStage<?> other, Runnable action)  | 
- 使用示例
 
1  | java复制代码//第一个异步任务,休眠1秒,保证最晚执行晚  | 
上一个任务或者other任务完成, 运行action,依赖最先完成任务的结果,无返回值
1  | java复制代码public CompletableFuture<Void> acceptEither(CompletionStage<? extends T> other,  | 
- 使用示例
 
1  | java复制代码//第一个异步任务,休眠1秒,保证最晚执行晚  | 
上一个任务或者other任务完成, 运行fn,依赖最先完成任务的结果,有返回值
1  | java复制代码public <U> CompletableFuture<U> applyToEither(CompletionStage<? extends T> other,  | 
- 使用示例
 
1  | java复制代码//第一个异步任务,休眠1秒,保证最晚执行晚  | 
5 处理任务结果或者异常
exceptionally-处理异常
1  | java复制代码public CompletableFuture<T> exceptionally(Function<Throwable, ? extends T> fn)  | 
- 如果之前的处理环节有异常问题,则会触发exceptionally的调用相当于 try…catch
 - 使用示例
 
1  | java复制代码CompletableFuture<Integer> first = CompletableFuture  | 
handle-任务完成或者异常时运行fn,返回值为fn的返回
- 相比exceptionally而言,即可处理上一环节的异常也可以处理其正常返回值
 
1  | java复制代码public <U> CompletableFuture<U> handle(BiFunction<? super T, Throwable, ? extends U> fn)  | 
- 使用示例
 
1  | java复制代码CompletableFuture<Integer> first = CompletableFuture  | 
whenComplete-任务完成或者异常时运行action,有返回值
- whenComplete与handle的区别在于,它不参与返回结果的处理,把它当成监听器即可
 - 即使异常被处理,在CompletableFuture外层,异常也会再次复现
 - 使用whenCompleteAsync时,返回结果则需要考虑多线程操作问题,毕竟会出现两个线程同时操作一个结果
 
1  | java复制代码public CompletableFuture<T> whenComplete(BiConsumer<? super T, ? super Throwable> action)  | 
- 使用示例
 
1  | java复制代码CompletableFuture<AtomicBoolean> first = CompletableFuture  | 
6 多个任务的简单组合
1  | java复制代码public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)  | 
- 使用示例
 
1  | java复制代码 CompletableFuture<Void> future = CompletableFuture  | 
8 取消执行线程任务
1  | java复制代码// mayInterruptIfRunning 无影响;如果任务未完成,则返回异常  | 
- 使用示例
 
1  | java复制代码CompletableFuture<Integer> future = CompletableFuture  | 
9 任务的获取和完成与否判断
1  | java复制代码// 任务是否执行完成  | 
- 使用示例
 
1  | java复制代码CompletableFuture<Integer> future = CompletableFuture  | 
欢迎指正文中错误
本文转载自: 掘金