从CompletableFuture到异步编程设计,笔者就分为2部分来分享CompletableFuture异步编程设计,前半部分总结下CompletableFuture使用实践,后半部分分享下CompletableFuture实现原理和异步编程设计机制。
(ps:本文内容较多,请耐心阅读。如果读者了解CompletableFuture使用的话,可以直接看后半部分内容;如果熟悉CompletableFuture及异步编程设计的话,可以直接翻到文档末尾点个“推荐”就好了,因为你已经掌握了Java异步设计精髓了 :) ,若有不正确地方,感谢评论区指正交流~ )
Java8新增了CompletableFuture类,该类实现了CompletionStage和Future接口,简化了Java异步编程能力,该类方法较多,其实套路只有一个,那就是任务执行完成之后执行“回调”。
CompletableFuture使用实践
Java8新增的CompletableFuture 提供对异步计算的支持,可以通过回调的方式处理计算结果。CompletableFuture 类实现了CompletionStage和Future接口,所以还可以像之前使用Future那样使用CompletableFuture ,尽管已不再推荐这样用了。
CompletableFuture的创建
// 创建一个带result的CompletableFutureCompletableFuture<String> future = CompletableFuture.completedFuture("result"); future.get(); // 默认创建的CompletableFuture是没有result的,这时调用future.get()会一直阻塞下去知道有result或者出现异常future = new CompletableFuture<>(); try { future.get(1, TimeUnit.SECONDS); } catch (Exception e) { // no care} // 给future填充一个resultfuture.complete("result"); assert "result".equals(future.get()); // 给future填充一个异常future = new CompletableFuture<>(); future.completeExceptionally(new RuntimeException("exception")); try { future.get(); } catch (Exception e) { assert "exception".equals(e.getCause().getMessage()); }
上面的示例是自己设置future的result,一般情况下我们都是让其他线程或者线程池来执行future这些异步任务。除了直接创建CompletableFuture 对象外(不推荐这样使用),还可以使用如下4个方法创建CompletableFuture 对象:
// runAsync是Runnable任务,不带返回值的,如果入参有executor,则使用executor来执行异步任务public static CompletableFuture<Void> runAsync(Runnable runnable) public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor) // supplyAsync是待返回结果的异步任务public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor) // 使用示例CompletableFuture.runAsync(() -> { System.out.println("hello world"); }, executor); CompletableFuture.supplyAsync(() -> { System.out.println("hello world"); return "result"; });
