Future详解( 五 )


1.runAsync 方法以Runnable函数式接口类型为参数 , 没有返回结果,supplyAsync 方法Supplier函数式接口类型为参数,返回结果类型为U;Supplier 接口的 get() 方法是有返回值的(会阻塞) 。
2.没有指定Executor的方法会使用ForkJoinPool.commonPool() 作为它的线程池执行异步代码 。如果指定线程池,则使用指定的线程池运行 。
3.默认情况下 CompletableFuture 会使用公共的 ForkJoinPool 线程池,这个线程池默认创建的线程数是 CPU 的核数(也可以通过 JVM option:-Djava.util.concurrent.ForkJoinPool.common.parallelism 来设置 ForkJoinPool 线程池的线程数) 。如果所有 CompletableFuture 共享一个线程池 , 那么一旦有任务执行一些很慢的 I/O 操作,就会导致线程池中所有线程都阻塞在 I/O 操作上,从而造成线程饥饿,进而影响整个系统的性能 。所以,强烈建议你要根据不同的业务类型创建不同的线程池,以避免互相干扰 。
3)supplyAsync的两种获取结果的方法join&get
1.join()和get()方法都是用来获取CompletableFuture异步之后的返回值 。join()方法抛出的是uncheck异常(即未经检查的异常),不会强制开发者抛出 。get()方法抛出的是经过检查的异常 , ExecutionException, InterruptedException 需要用户手动处理(抛出或者 try catch)
【3】常用方法的使用与介绍
1)结果处理
1.介绍:
//当CompletableFuture的计算结果完成,或者抛出异常的时候 , 我们可以执行特定的 Action 。主要是下面的方法:public CompletableFuture<T> whenComplete(BiConsumer<? super T,? super Throwable> action)public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action)public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action, Executor executor)//Action的类型是BiConsumer<? super T,? super Throwable>,它可以处理正常的计算结果 , 或者异常情况 。//方法不以Async结尾,意味着Action使用相同的线程执行,而Async可能会使用其它的线程去执行(如果使用相同的线程池 , 也可能会被同一个线程选中执行) 。//这几个方法都会返回CompletableFuture,当Action执行完毕后它的结果返回原始的CompletableFuture的计算结果或者返回异常2.示例:
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {}if (new Random().nextInt(10) % 2 == 0) {int i = 12 / 0;}System.out.println("执行结束!");return "test";});//whenComplete一般搭配exceptionally一起使用 , 一个处理结果,一个处理异常future.whenComplete(new BiConsumer<String, Throwable>() {@Overridepublic void accept(String t, Throwable action) {System.out.println(t+" 执行完成!");}});future.exceptionally(new Function<Throwable, String>() {@Overridepublic String apply(Throwable t) {System.out.println("执行失败:" + t.getMessage());return "异常xxxx";}});2)结果转换
1.介绍:所谓结果转换,就是将上一段任务的执行结果作为下一阶段任务的入参参与重新计算,产生新的结果 。
2.方法列举:
【1】thenApply
1.说明
//thenApply 接收一个函数作为参数,使用该函数处理上一个CompletableFuture 调用的结果,并返回一个具有处理结果的Future对象 。public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn)public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn)2.示例
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {int result = 100;System.out.println("一阶段:" + result);return result;}).thenApply(number -> {int result = number * 3;System.out.println("二阶段:" + result);return result;});【2】thenCompose
1.说明
//thenCompose 的参数为一个返回 CompletableFuture 实例的函数,该函数的参数是先前计算步骤的结果 。public <U> CompletableFuture<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn);public <U> CompletableFuture<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn) ;2.示例
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(new Supplier<Integer>() {@Overridepublic Integer get() {int number = new Random().nextInt(30);System.out.println("第一阶段:" + number);return number;}}).thenCompose(new Function<Integer, CompletionStage<Integer>>() {@Overridepublic CompletionStage<Integer> apply(Integer param) {return CompletableFuture.supplyAsync(new Supplier<Integer>() {@Overridepublic Integer get() {int number = param * 2;System.out.println("第二阶段:" + number);return number;}});}});

推荐阅读