目录
3.7 异常传递 有返回值 跟whenComplete基本一致,区别在于handle的回调方法有返回值。
3.8.1 多任务合并thenCombine、thenAcceptBoth 和runAfterBoth
3.8.2 选择最快执行完毕的CompletableFuture,然后再选择不同的处理方式接着处理.
3.10 多个 CompletableFuture 组合在一起
1.什么是CompletableFuture?
先看下源码 拉到最下面 有demo 参照
public class CompletableFuture<T> implements Future<T>, CompletionStage<T>
简单了解下Future JDK5 新增了 Future 接口,用于描述一个异步计算的结果。 Future 的使用方法提供了异步执行任务的能力,但是对于结果的获取却是很不方便,只能通过阻塞或者轮询的方式得到任务的结果。阻塞的方式显然和我们的异步编程的初衷相违背,轮询的方式又会耗费无谓的 CPU 资源,而且也不能及时地得到计算结果。
CompletionStage接口定义了任务编排的方法,执行某一阶段,可以向下执行后续阶段。(看下源码)
所以在jdk8中引入了CompletableFuture,对Future的扩展和增强。
也就是处理多任务的协同工作的方法。
2.什么场景下使用,在项目中使用场景?
比如全景统计,报表分析 提高后端响应速度,方便联调测试,一个接口将数据查询出来。
3.方法的使用详情
3.1 创建CompletableFuture对象
public static CompletableFuture<Void> runAsync(Runnable runnable);
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor);
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier);
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor);
3.2 获取任务结果方法
// 如果完成则返回结果,否则就抛出具体的异常
public T get() throws InterruptedException, ExecutionException
// 最大时间等待返回结果,否则就抛出具体异常
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
// 完成时返回结果值,否则抛出unchecked异常。为了更好地符合通用函数形式的使用,如果完成此 CompletableFuture所涉及的计算引发异常,则此方法将引发unchecked异常并将底层异常作为其原因 不会强制开发者抛出。get()方法抛出的是经过检查的异常,ExecutionException, InterruptedException 需要用户手动处理(抛出或者 try catch)
public T join()
// 如果完成则返回结果值(或抛出任何遇到的异常),否则返回给定的 valueIfAbsent。
public T getNow(T valueIfAbsent)
// 如果任务没有完成,返回的值设置为给定值
public boolean complete(T value)
// 如果任务没有完成,就抛出给定异常
public boolean completeExceptionally(Throwable ex)
3.3 异步回调处理 有参数有返回值
thenApply和thenApplyAsync区别在于,使用thenApply方法时子任务与父任务使用的是同一个线程,而thenApplyAsync在子任务中是另起一个线程执行任务,并且thenApplyAsync可以自定义线程池,默认的使用ForkJoinPool.commonPool()线程池。
public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn, Executor executor)
3.4 结果消费 有参数无返回
thenAccept在上一个任务执行结束后,将上一个任务返回结果作为入参,但无返回
public CompletableFuture<Void> thenAccept(Consumer<? super T> action),
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action),
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action,Executor executor)
3.5 结果消费 无参数无返回值

public CompletableFuture<Void> thenRun(Runnable action)
public CompletableFuture<Void> thenRunAsync(Runnable action)
public CompletableFuture<Void> thenRunAsync(Runnable action,Executor executor)
3.6 异常传递 无返回值
whenComplete是当某个任务执行完成后执行的回调方法,会将执行结果或者执行期间抛出的异常传递给回调方法,如果是正常执行则异常为null,回调方法对应的CompletableFuture的result和该任务一致,如果该任务正常执行,则get方法返回执行结果,如果是执行异常,则get方法抛出异常。
public CompletableFuture<T> whenComplete(BiConsumer<? super T, ? super Throwable> action) {return uniWhenCompleteStage(null, action)
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action)
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action, Executor executor)
3.7 异常传递 有返回值 跟whenComplete基本一致,区别在于handle的回调方法有返回值。
public <U> CompletableFuture<U> handle(BiFunction<? super T, Throwable, ? extends U> fn),
public <U> CompletableFuture<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn),
public <U> CompletableFuture<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn, Executor executor)
3.8.1 多任务合并thenCombine、thenAcceptBoth 和runAfterBoth
这三个方法都是将两个CompletableFuture组合起来处理,只有两个任务都正常完成时,才进行下阶段任务。
三种方法也含有thenCombineAsync、 thenAcceptBothAsync、 runAfterBothAsync方法 也可指定自定义线程池
区别:thenCombine会将两个任务的执行结果作为所提供函数的参数,且该方法有返回值;thenAcceptBoth同样将两个任务的执行结果作为方法入参,但是无返回值;runAfterBoth没有入参,也没有返回值
public <U,V> CompletableFuture<V> thenCombine(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn);
public <U> CompletionStage<Void> thenAcceptBoth(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action);
public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other,Runnable action);
public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action, Executor executor);
3.8.2 选择最快执行完毕的CompletableFuture,然后再选择不同的处理方式接着处理.
区别:applyToEither有参数有返回值 acceptEither,runAfterEither无返回值 ; runAfterEither无参数 三个方法 带有异步执行 也可定义线程池
这种组合模式只要有一个异步任务成功,就会触发后续的方法,比如我们组合任务1和任务2,如果任务1执行完成就直接执行任务3,无视任务2。反之任务2先完成直接执行任务3,无视任务1。
public <U> CompletableFuture<U> applyToEither(CompletionStage<? extends T> other, Function<? super T, U> fn);
public CompletableFuture<Void> acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action);
public CompletableFuture<Void> runAfterEither(CompletionStage<?> other,Runnable action);
public CompletableFuture<Void> acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action,Executor executor);
3.9 异常捕获
任务1执行过程中可能报错,我们希望能够从逻辑的角度处理掉,那么我们就可以在任务1后面接一个exceptionally方法,然后再接上任务2。这样一来,任务1执行报错就会走到exceptionally,反之就会走到任务2的代码段
public CompletableFuture<T> exceptionally(Function<Throwable, ? extends T> fn)
3.10 多个 CompletableFuture 组合在一起
allof多个任务都执行完成后才会执行,只有有一个任务执行异常,则返回的CompletableFuture执行get方法时会抛出异常,如果都是正常执行,则get返回null。
anyof是多个任务只要有一个任务执行完成,则返回的CompletableFuture执行get方法时会抛出异常,如果都是正常执行,则get返回执行完成任务的结果。
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)
CompletableFuture是多个任务都执行完成后才会执行,只有有一个任务执行异常,则返回的CompletableFuture执行get方法时会抛出异常,如果都是正常执行,则get返回null。
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
CompletableFuture是多个任务只要有一个任务执行完成,则返回的CompletableFuture执行get方法时会抛出异常,如果都是正常执行,则get返回执行完成任务的结果。
依赖关系
依赖关系
thenApply():把前面任务的执行结果,交给后面的Function
thenCompose():用来连接两个有依赖关系的任务,结果由第二个任务返回
and集合关系
thenCombine():合并任务,有返回值
thenAccepetBoth():两个任务执行完成后,将结果交给thenAccepetBoth处理,无返回值
runAfterBoth():两个任务都执行完成后,执行下一步操作(Runnable类型任务)
or聚合关系
applyToEither():两个任务哪个执行的快,就使用哪一个结果,有返回值
acceptEither():两个任务哪个执行的快,就消费哪一个结果,无返回值
runAfterEither():任意一个任务执行完成,进行下一步操作(Runnable类型任务)
并行执行
allOf():当所有给定的 CompletableFuture 完成时,返回一个新的 CompletableFuture
anyOf():当任何一个给定的CompletablFuture完成时,返回一个新的CompletableFuture
结果处理
whenComplete:当任务完成时,将使用结果(或 null)和此阶段的异常(或 null如果没有)执行给定操作
exceptionally:返回一个新的CompletableFuture,当前面的CompletableFuture完成时,它也完成,当它异常完成时,给定函数的异常触发这个CompletableFuture的完成
demo 方便了解及使用
public class demo01 {
/**
* 创建对象返回结果
* @throws ExecutionException
* @throws InterruptedException
*/
@Test
public void demo01() throws ExecutionException, InterruptedException{
CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
System.out.println("do something....");
return "result";
});
//等待任务执行完成
System.out.println("结果->" + cf.get());
}
/**
* 创建对象指定线程池
* @throws ExecutionException
* @throws InterruptedException
*/
@Test
public void demo02() throws ExecutionException, InterruptedException{
// 自定义线程池
ExecutorService executorService = Executors.newSingleThreadExecutor();
CompletableFuture<List<String>> cf = CompletableFuture.supplyAsync(() -> {
System.out.println("do something222....");
return Arrays.asList("result");
}, executorService);
//等待子任务执行完成
System.out.println("结果->" + cf.get());
}
/**
* 获取结果
* @throws InterruptedException
* @throws ExecutionException
* @throws TimeoutException
*/
@Test
public void demo03() throws InterruptedException, ExecutionException, TimeoutException {
// 自定义线程池
ExecutorService executorService = Executors.newSingleThreadExecutor();
CompletableFuture<List<String>> cf = CompletableFuture.supplyAsync(() -> {
System.out.println("do something333....");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return Arrays.asList("result");
}, executorService);
//等待子任务执行完成
System.out.println("结果->" + cf.get(1000, TimeUnit.MILLISECONDS));
// System.out.println("结果->" + cf.join());
}
/**
* 异步回调处理 thenApply和thenApplyAsync
*
*
* Thread[ForkJoinPool.commonPool-worker-3,5,main] cf1 do something....
* Thread[ForkJoinPool.commonPool-worker-5,5,main] cf2 do something....
* cf1结果->1
* cf2结果->3
*/
@Test
public void demo04(){
CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread() + " cf1 do something....");
return 1;
});
CompletableFuture<Integer> cf2 = cf1.thenApply((result) -> {
System.out.println(Thread.currentThread() + " cf2 do something....");
result += 2;
return result;
});
//等待任务1执行完成
System.out.println("cf1结果->" + cf1.join());
//等待任务2执行完成
System.out.println("cf2结果->" + cf2.join());
CompletableFuture<String> stringCompletableFuture = cf1.thenApply((result) -> {
int p = 1/0;
return result + "第一次 + ";
}).thenApply((result) -> {
return result + "第二次";
});
System.out.println("合在一起结果->" + stringCompletableFuture.join());
}
/**
* 异步回调处理 thenApply和thenApplyAsync
* 有参数 有返回值
*/
@Test
public void demo05(){
CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread() + " cf1 do something....");
return 1;
});
CompletableFuture<Integer> cf2 = cf1.thenApplyAsync((result) -> {
System.out.println(Thread.currentThread() + " cf2 do something....");
result += 2;
return result;
});
//等待任务1执行完成
System.out.println("cf1结果->" + cf1.join());
//等待任务2执行完成
System.out.println("cf2结果->" + cf2.join());
}
/**
* 结果消费
* thenAccept和thenAcceptAsync
* 有参数 无返回值
*/
@Test
public void demo06(){
CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {
return "初始结果";
});
cf1.thenAccept((result) -> {
String finalresult = "最终结果 ---" + result;
System.out.println("两次结果->" + finalresult);
});
}
/**
* 结果消费
* thenRun和thenRunAsync
* 无参数 无返回值
*/
@Test
public void demo07(){
CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {
return "初始结果";
});
CompletableFuture<Void> thenRun = cf1.thenRun(() -> {
System.out.println("do something ....");
});
System.out.println("cf1结果->" + cf1.join());
System.out.println("thenRun结果->" + thenRun.join());
}
/**
* 结果消费
* whenComplete和whenCompleteAsync
* 无参数 无返回值
*/
@Test
public void demo08() {
CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {
int p = 1 / 0;
return "初始结果";
});
CompletableFuture<String> cf2 = cf1.whenComplete((result, e) -> {
System.out.println("上个任务结果:" + result);
System.out.println("上个任务抛出异常:" + e);
System.out.println(Thread.currentThread() + " cf2 do something....");
});
}
/**
* 结果消费
* handle和handleAsync
* 无参数 无返回值
*/
@Test
public void demo09(){
CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {
// int p = 1/0;
return "初始结果";
});
CompletableFuture<String> cf2 = cf1.handle((result, e) -> {
System.out.println("上个任务结果:" + result);
System.out.println("上个任务抛出异常:" + e);
String finalResult = result + "-- 最终结果";
return finalResult;
});
System.out.println("最终结果:" + cf2.join());
}
/**
* 组合
*
*
* cf1 执行结果->73
* cf2 执行结果->85
* thenCombine返回结果 ->158
* thenAcceptBoth 返回结果7385
* thenAcceptBoth 返回结果null
* runAfterBoth do something....
* runAfterBoth 返回结果null
*/
@Test
public void demo10(){
CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(() -> {
int result1 = RandomUtil.randomInt(10, 100);
System.out.println("cf1 执行结果->" + result1);
// int p =1/0;
return result1;
});
CompletableFuture<Integer> cf2 = CompletableFuture.supplyAsync(() -> {
int result2 = RandomUtil.randomInt(10, 100);
System.out.println("cf2 执行结果->" + result2);
return result2;
});
CompletableFuture<Integer> cf9 = CompletableFuture.supplyAsync(() -> {
int result3 = RandomUtil.randomInt(10, 100);
System.out.println("cf9 执行结果->" + result3);
return result3;
});
CompletableFuture<Integer> cf3 = cf1.thenCombine(cf2, (result1, result2) -> {
return result1 + result2;
});
System.out.println("thenCombine返回结果 ->" + cf3.join());
CompletableFuture<Void> voidCompletableFuture = cf1.thenAcceptBoth(cf2, (result1, result2) -> {
System.out.println("thenAcceptBoth 返回结果->" + result1 + result2);
});
System.out.println("thenAcceptBoth 返回结果->" + voidCompletableFuture.join());
CompletableFuture<Void> runAfterBoth = cf1.runAfterBoth(cf2, () -> {
System.out.println("runAfterBoth do something....");
});
System.out.println("runAfterBoth 返回结果->" + runAfterBoth.join());
}
/**
* 异常捕获
*/
@Test
public void demo11(){
CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {
int p = 1/0;
return "初始结果";
}).exceptionally(e -> {
System.out.println("xxx接口查询数据异常" + e.getMessage());
return null;
});
}
/**
* 组合
*/
@Test
public void demo12() {
HashMap<String, Object> map = new HashMap<>(2);
CompletableFuture<HashMap<String, Object>> jigouanjianzongshu = CompletableFuture.supplyAsync(() -> {
System.out.println("各机构案件总数当前线程:" + Thread.currentThread().getId());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
map.put("各机构案件总数", "jigouanjianzongshu");
return map;
}).exceptionally(e -> {
System.out.println("各机构案件总数执行有误");
return null;
});
CompletableFuture<HashMap<String, Object>> shuziheji = CompletableFuture.supplyAsync(() -> {
System.out.println("数字合计当前线程:" + Thread.currentThread().getId());
// int p = 1/0;
map.put("数字合计", "shuziheji");
return map;
}).exceptionally(e -> {
System.out.println("数字合计查询执行有误");
return null;
});
CompletableFuture<Void> allCombindFuture = CompletableFuture.allOf(jigouanjianzongshu, shuziheji);
System.out.println("执行结果" + allCombindFuture.join());
// CompletableFuture<Object> objectCompletableFuture = CompletableFuture.anyOf(jigouanjianzongshu, shuziheji);
// System.out.println("执行结果" + objectCompletableFuture.join());
System.out.println(map);
}
}