一:创建对象
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);
说明:没有指定Executor的方法会使用ForkJoinPool.commonPool() 作为它的线程池执行异步代码。如果指定线程池,则使用指定的线程池运行。
- runAsync方法不支持返回值。
- supplyAsync 支持返回值。
示例:
/**
* CompletableFuture 提供了四个静态方法来创建一个异步操作。
*
*/
public class CompletableFutureDemo1 {
public static void main(String[] args) {
/** 第一种 runAsync 不支持返回值的 */
CompletableFuture<Void> runAsync = CompletableFuture.runAsync(() -> {
System.out.println("runAsync 不支持返回值");
}).whenComplete((t,u)->{
System.out.println("runAsync 完成");
});
/** 第二种 supplyAsync 支持返回值 */
CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
int i = 10;
return i;
}).whenComplete((t, u) -> {
System.out.println("supplyAsync 完成,返回值是" + t);
});
}
}
运行结果:
runAsync 不支持返回值
runAsync 完成
supplyAsync 完成,返回值是10
二:计算完成时回调方法
当CompletableFuture的计算结果完成,或者抛出异常的时候,可以执行特定的Action。主要是下面的方法:
public CompletableFuture<T> whenComplete(BiConsumer<? super T,? super Throwable> action);
返回相同的结果或例外,这一阶段的新completionstage,这个阶段完成时,执行特定动作的结果(或 null如果没有)和异常(或 null如果没有)这个阶段。
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action);
返回相同的结果或例外,这一阶段的新completionstage,这个阶段完成时,执行特定动作执行给定的操作这一阶段的默认的异步执行设施,其结果(或 null如果没有)和异常(或 null如果没有)这个阶段作为参数。
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action, Executor executor);
返回相同的结果或例外,这一阶段的新completionstage,这个阶段完成时,执行使用所提供的遗嘱执行人,给出的行动与结果(或 null如果没有)和异常(或 null如果没有)这个阶段作为参数。
public CompletableFuture<T> exceptionally(Function<Throwable,? extends T> fn);
返回一个新的completablefuture已经完成与给定值。
示例:
/**
* whenCompleteAsync 依赖于上一层的CompletableFuture 的返回值作为这个阶段的参数进行某些操作,返回的仍然是上一层的CompletableFuture
* whenCompleteAsync和whenComplete的区别:
* whenCompleteAsync为异步,可能并不是执行上一层代码的线程
* whenComplete为执行上一层代码的线程执行这个阶段的逻辑
*
*/
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
int i = 10 / 2;
return i;
}).whenCompleteAsync((t, u) -> {
int m = t*2; //可以利用回调值做一些操作计算
System.out.println("上一层依赖的CompletableFuture返回的结果是:" + t);
System.out.println("上一层依赖的CompletableFuture返回的结果是:" + u);
});
Integer result = future.get();
System.out.println("CompletableFuture.whenCompleteAsync运行后结果是:"+result);
运行结果:
上一层依赖的CompletableFuture返回的结果是:5
上一层依赖的CompletableFuture返回的结果是:null
CompletableFuture.whenCompleteAsync运行后结果是:5
运行后可以发现whenCompleteAsync(BiConsumer<? super T,? super Throwable> action)中的第一个参数即是上一层回调的返回值,那第二个参数是什么呢?看下面这个示例
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
int i = 10 / 0;
return i;
}).whenCompleteAsync((t, u) -> {
System.out.println("上一层依赖的CompletableFuture返回的结果t是:" + t);
System.out.println("上一层依赖的CompletableFuture返回的结果u是:" + u);
});
运行结果:
上一层依赖的CompletableFuture返回的结果t是:null
上一层依赖的CompletableFuture返回的结果u是:java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
所以第二个参数就是上一层回调出现的异常信息。OK
那么exceptionally这个方法则是在回调时遇到异常后可以进行的某些操作,看一个示例:
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
int i = 10 / 0;
return i;
}).exceptionally(t -> {
System.out.println("返回结果t:" + t);
return 100;
});
System.out.println("CompletableFuture.exceptionally运行结果:"+future1.get());
运行结果:
返回结果t:java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
CompletableFuture.exceptionally运行结果:100
所以在exceptionally方法中可以在接收到回调方法异常时可以做一些操作。
三:线程串行化方法
thenApply 方法:当一个线程依赖另一个线程时,获取上一个任务返回的结果,并返回当前任务的返回值。
thenAccept方法:消费处理结果。接收任务的处理结果,并消费处理,无返回结果。
thenRun方法:只要上面的任务执行完成,就开始执行thenRun,只是处理完任务后,执行 thenRun的后续操作
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)
当一个线程依赖另一个线程时,获取上一个任务返回的结果,**并返回当前任务的返回值**。(有返回值)
public CompletionStage<Void> thenAccept(Consumer<? super T> action);
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action);
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action,Executor executor);
消费处理结果。接收任务的处理结果,并消费处理,**无返回结果。
public CompletionStage<Void> thenRun(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action,Executor executor);
只要上面的任务执行完成,就开始执行thenRun,**只是处理完任务后,执行 thenRun的后续操作
每一个方法都对应了三种操作。带有Async默认是异步执行的。这里所谓的异步指的是不在当前线程内执行。带有参数Executor executor的则用指定的线程池方案,不指定的话则用默认的ForkJoinPool.commonPool()。
说明:(Function<? super T,? extends U> fn)
T : 上一个任务返回结果的类型
U:当前任务的返回值的类型
示例thenApplyAsync:
@Test
public void testThenApply() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> thenApply = CompletableFuture.supplyAsync(() -> {
return 100;
}).thenApplyAsync(t -> {
return t * 2;
});
Integer result = thenApply.get();
System.out.println(result);
}
运行结果:200
示例
@Test
public void testThenAcceptAsync() throws ExecutionException, InterruptedException {
CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
return 100;
}).thenAcceptAsync(t -> {
t = t*2;
System.out.println("t========>"+t);
});
System.out.println(future.get());
}
运行结果:t========>200
null
四:两任务组合 - 都要完成
两个任务必须都完成,触发该任务。
thenCombine:组合两个future,获取两个future任务的返回结果,并返回当前任务的返回值
thenAcceptBoth:组合两个future,获取两个future任务的返回结果,然后处理任务,没有返回值。
runAfterBoth:组合两个future,不需要获取future的结果,只需两个future处理完任务后,处理该任务
public <U,V> CompletableFuture<V> thenCombine(
CompletionStage<? extends U> other,
BiFunction<? super T,? super U,? extends V> fn);
public <U,V> CompletableFuture<V> thenCombineAsync(
CompletionStage<? extends U> other,
BiFunction<? super T,? super U,? extends V> fn);
public <U,V> CompletableFuture<V> thenCombineAsync(
CompletionStage<? extends U> other,
BiFunction<? super T,? super U,? extends V> fn, Executor executor);
组合两个future,获取两个future任务的返回结果,并返回当前任务的返回值
public <U> CompletableFuture<Void> thenAcceptBoth(
CompletionStage<? extends U> other,
BiConsumer<? super T, ? super U> action);
public <U> CompletableFuture<Void> thenAcceptBothAsync(
CompletionStage<? extends U> other,
BiConsumer<? super T, ? super U> action);
public <U> CompletableFuture<Void> thenAcceptBothAsync(
CompletionStage<? extends U> other,
BiConsumer<? super T, ? super U> action, Executor executor);
组合两个future,获取两个future任务的返回结果,然后处理任务,没有返回值。
public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other,
Runnable action);
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,
Runnable action);
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,
Runnable action,
Executor executor);
组合两个future,不需要获取future的结果,只需两个future处理完任务后,处理该任务
五:多任务组合
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs);
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs);
说明:
allOf:等待所有任务完成
anyOf:只要有一个任务完成