前言
以前需要异步执行一个任务时,一般是用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 |
欢迎指正文中错误
本文转载自: 掘金