java 异步编程( 二 )

【java 异步编程】使用 CountDownLatch 将异步代码转换为同步返回,这只是另一个实现
Futurepublic interface Future<V> {/*** 尝试取消这个任务的执行.* 如果任务执行完成之后,调用 cancel 返回 false.* 如果任务已经被取消了,调用 cancel 也会返回 false** 如果任务已经执行了, mayInterruptIfRunning 标志是否中断执行任务的线程.* mayInterruptIfRunning 为 true 会触发线程的中断(当线程睡眠,会抛出异常 InterruptedException),* 为 false 时不中断任务执行,只改变 Future 的状态** 调用了 cancel 方法,调用 get 方法会抛出异常*/boolean cancel(boolean mayInterruptIfRunning);/*** 任务完成之前调用 cancel ,此方法返回 true*/boolean isCancelled();/*** 任务完成返回 true*/boolean isDone();/*** 等待任务完成,然后返回其结果* @return the computed result* @throws CancellationException if the computation was cancelled* @throws ExecutionExceptionif the computation threw anexception* @throws InterruptedExceptionif the current thread was interrupted while waiting*/V get() throws InterruptedException, ExecutionException;/*** 等待任务完成,然后返回其结果.超时没有返回,抛出异常 TimeoutException*/V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;}Future.cancel(true) 会触发线程休眠的中断,即 TimeUnit.SECONDS.sleep(10); 会抛出异常 。
Future.cancel(true) 或者 Future.cancel(false) 都会触发 Future.get() 异常 。
public static void main(String[] args) throws ExecutionException, InterruptedException {final Future<String> submit = THREAD_POOL_EXECUTOR.submit(() -> {System.out.println("任务开始执行");try {TimeUnit.SECONDS.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("任务执行完毕");return "ok";});THREAD_POOL_EXECUTOR.execute(() -> {System.out.println("执行 submit.cancel");try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}submit.cancel(false);});// submit.get();System.out.println("整个流程执行结束");}JDK 提供 Future 的实现 FutureTask 源码相对较简单,不再展开 。
CompletableFuture由于 Future 使用的局限性:不能链式调用、多个异步计算的结果不能传递下一个异步任务(可以做到,但是编程稍微复杂),异步执行异常的捕获处理
从 JDK 1.8 开始,大佬 Doug Lea 带来了更加容易的异步编程模型,CompletableFuture 。
CompletableFuture 可以做到
1、获取异步执行的结果链式传递下一个异步去执行
2、异步执行时,你有机会处理异步执行时发生的异常
总之,CompletableFuture 很想 。
CompletableFuture 实现比较复杂,有的地方不是那么容易理解,当你理解其实现思想,你也算是一只脚迈入了响应式编程中去了 。
开胃小菜public class CompletableFutureBlog1 {public static void main(String[] args) throws ExecutionException, InterruptedException {final Stopwatch started = Stopwatch.createStarted();// 洗水壶,烧水CompletableFuture<String> completableFuture1 = CompletableFuture.supplyAsync(() -> {System.out.println("洗水壶");System.out.println("烧水");try {TimeUnit.SECONDS.sleep(16);} catch (InterruptedException e) {e.printStackTrace();}return "洗水壶 -> 烧水";});// 洗茶壶,洗茶杯 -> 拿茶叶CompletableFuture<String> completableFuture2 =CompletableFuture.supplyAsync(() -> {System.out.println("洗茶壶");System.out.println("洗茶杯");System.out.println("拿茶叶");try {TimeUnit.SECONDS.sleep(4);} catch (InterruptedException e) {e.printStackTrace();}return "洗茶壶,洗茶杯 -> 拿茶叶";});// 组合二者异步运算的结果,传递给方法计算final CompletableFuture<String> completableFuture = completableFuture2.thenCombine(completableFuture1, (result2, result1) -> {System.out.println(StrUtil.format("result2 是 洗茶壶,洗茶杯 -> 拿茶叶: {}", result2));System.out.println(StrUtil.format("result1 是 洗水壶 -> 烧水: {}", result1));System.out.println("泡茶");return "泡茶";});completableFuture.get();System.out.println("执行时间: " + started.elapsed(TimeUnit.SECONDS));}}runAsync 和 supplyAsync 的区别runAsync 和 supplyAsync 区别就是你是否需要获取异步计算的结果 。当你需要异步处理的结果,你需要 supplyAsync


推荐阅读