一,CompletableFuture 异步编排
CompletableFuture提供了四个静态方法来创建一个异步操作
//传入一个Runnable,特点是无需返回值
public static CompletableFuture<Void> runAsync(Runnable runnable)
//传入一个Runnable,特点是无需返回值,可以指定在那个线程池中执行,即Executor
public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor)
//传入一个要执行的异步任务,但是有返回值
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
//传入一个要执行的异步任务,但是有返回值,可以指定在那个线程池中执行,即Executor
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor)
1,创建异步方法
(1),使用runAsync测试
public class CompletableFutureTest {
//创建线程池,不建议使用该方法创建,本文主要是讲解CompletableFuture,线程池部分不详细介绍
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) {
System.out.println("main方法开始。。。");
CompletableFuture.runAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("运行结果:" + i);
},executor);//使用我们自己的线程池
System.out.println("main方法结束。。。");
}
}
运行结果:
main方法开始。。。
main方法结束。。。
当前线程:11
运行结果:5
(2),使用supplyAsync测试
public class CompletableFutureTest {
//创建线程池,不建议使用该方法创建,本文主要是讲解CompletableFuture,线程池部分不详细介绍
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main方法开始。。。");
//只要启动异步任务,都会返回一个CompletableFuture
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("运行结果:" + i);
return i;
}, executor);
//获取异步任务的返回值
Integer integer = future.get();
System.out.println("main方法结束。。。" + integer);
}
}
运行结果:
main方法开始。。。
当前线程:11
运行结果:5
main方法结束。。。5
(3),总结
1,runXxxx 都是没有返回结果的,supplyXxx 都是可以获取返回结果的
2,可以传入自定义的线程池,否则就用默认的线程池;
2,CompletableFuture完成回调与异常感知
计算完成时回调方法
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);
public completableFuture<T> exceptiona1ly(Function<Throwable,? extends T fn);
细节
1,whenComplete 可以处理正常和异常的计算结果,exceptionally 处理异常情况。
2,whenComplete 和 whenCompleteAsync 的区别:
(1), whenComplete:是执行当前任务的线程执行继续执行whenComplete 的任务。
(2),whenCompleteAsync:是执行把 whenCompleteAsync 这个任务继续提交给线程池 来进行执行。
public class CompletableFutureTest {
//创建线程池,不建议使用该方法创建,本文主要是讲解CompletableFuture,线程池部分不详细介绍
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main方法开始。。。");
//只要启动异步任务,都会返回一个CompletableFuture
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 0;
System.out.println("运行结果:" + i);
return i;
}, executor).whenComplete((res,exception) -> {
//虽然能得到异常信息,但是没法修改返回数据
System.out.println("异步任务成功完成了。。。结果是:" + res + "异常是:" + exception);
}).exceptionally(throwable -> {
//可以感知异常,同时返回默认值
return 10;
});
//获取异步任务的返回值
Integer integer = future.get();
System.out.println("main方法结束。。。" + integer);
}
}
运行结果:
main方法开始。。。
当前线程:11
异步任务成功完成了。。。结果是:null异常是:java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
main方法结束。。。10
注意
有异常才会进入exceptionally()方法,没有异常正常返回,
3,handle方法 (最终处理)
public class CompletableFutureTest {
//创建线程池,不建议使用该方法创建,本文主要是讲解CompletableFuture,线程池部分不详细介绍
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main方法开始。。。");
//方法执行完成后的处理
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("运行结果:" + i);
return i;
}, executor).handle((res,exec) -> {
if (res != null){
return res * 2;
}
if (exec != null){
return 0;
}
return 0;
});
//获取异步任务的返回值
Integer integer = future.get();
System.out.println("main方法结束。。。" + integer);
}
}
运行结果:
main方法开始。。。
当前线程:11
运行结果:5
main方法结束。。。20
注意:和 complete 一样,可对结果做最后的处理(可处理异常),可改变返回值。
4,线程串行化方法
public <Us CompletableFuture<Us thenApply(Function<? super T,? extends Us fn)
public <UsCompletableFuturecUz thenApplyAsyne(Function<? super T,? extends us 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,Executorexecutor);
public completionstage<Void> thenRun(Runnable action) ;
public completionstage<void> thenRunAsync(Runnable action);
public completionStage<Void> thenRunAsync(Runnable action,Executor executor );
(1),thenApply 方法:当一个线程依赖另一个线程时,获取上一个任务返回的结果,并返回当前 任务的返回值。
//thenApplyAsync:能接受上一步的结果,有返回值
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("运行结果:" + i);
return i;
}, executor).thenApplyAsync(res -> {
return "Hello" + res;
}, executor);
String s = future.get();
//获取异步任务的返回值
System.out.println("main方法结束。。。" + s);
(2), thenAccept 方法:消费处理结果。接收任务的处理结果,并消费处理,无返回结果。
//thenAcceptAsync:能接受上一步结果,但是无返回值
CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("运行结果:" + i);
return i;
}, executor).thenAcceptAsync(res -> {
System.out.println("任务2启动了。。。" + res);
},executor);
//获取异步任务的返回值
System.out.println("main方法结束。。。" );
(3),thenRun 方法:只要上面的任务执行完成,就开始执行thenRun,只是处理完任务后,执行 thenRun 的后续操作 带有 Async 默认是异步执行的。同之前。 以上都要前置任务成功完成。
//thenRun:不能获取到上一步的执行结果,无返回值
CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("运行结果:" + i);
return i;
}, executor).thenRunAsync(() -> {
System.out.println("任务2启动了。。。");
},executor);
//获取异步任务的返回值
System.out.println("main方法结束。。。" );
5,两任务组合 - 都要完成
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<? superT,? 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);
public UCompletableFuture<Void> thenAcceptBoth(Completionstage<? extends U> other ,Biconsumer<? super T, ? super U>action);
public <Us Completab1eFuture<void>thenAcceptBothAsync(CompletionStage<? extends U> other ,BiConsumer<? super T,?super U>action);
public <UsCompletab1eFuture<Void> thenAcceptBothAsync(completionstage<? extends U> other ,Biconsumer<? super T, ? super U>action,Executor executor);
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);
(1),thenCombine:组合两个 future,获取两个 future 的返回结果,并返回当前任务的返回值
CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务1线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("任务1结束:");
return i;
}, executor);
CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务2线程:" + Thread.currentThread().getId());
System.out.println("任务2结束:");
return "hello";
}, executor);
CompletableFuture<String> future = future01.thenCombineAsync(future02, (f1, f2) -> {
return f1 + ":::" + f2 + "->>world";
}, executor);
//获取异步任务的返回值
System.out.println("main方法结束。。。" + future.get());
/**
* 运行结果
* main方法开始。。。
* 任务1线程:11
* 任务1结束:
* 任务2线程:12
* 任务2结束:
* main方法结束。。。5:::hello->>world
*/
(2),thenAcceptBoth:组合两个 future,获取两个 future 任务的返回结果,然后处理任务,没有 返回值。
CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务1线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("任务1结束:");
return i;
}, executor);
CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务2线程:" + Thread.currentThread().getId());
System.out.println("任务2结束:");
return "hello";
}, executor);
future01.thenAcceptBothAsync(future02,(f1,f2) -> {
System.out.println("任务3开始----》之前的结果:" + f1 + "===>" + f2);
},executor);
//获取异步任务的返回值
System.out.println("main方法结束。。。");
/**
* 运行结果
* main方法开始。。。
* 任务1线程:11
* 任务1结束:
* 任务2线程:12
* 任务2结束:
* main方法结束。。。
* 任务3开始----》之前的结果:5===>hello
*/
(3),runAfterBoth:组合两个 future,不需要获取 future 的结果,只需两个 future 处理完任务后, 处理该任务。
CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务1线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("任务1结束:");
return i;
}, executor);
CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务2线程:" + Thread.currentThread().getId());
System.out.println("任务2结束:");
return "hello";
}, executor);
future01.runAfterBothAsync(future02,() -> {
System.out.println("任务3开始");
},executor);
//获取异步任务的返回值
System.out.println("main方法结束。。。");
/**
* 运行结果
* main方法开始。。。
* 任务1线程:11
* 任务1结束:
* main方法结束。。。
* 任务2线程:12
* 任务2结束:
* 任务3开始
*/
6、两任务组合 - 一个完成
public <U>completab1eFuture<U applyToEither(completionstage<? extends T> other,Function<? super T, U> fn);
public <U> completableFuturecU> applyToEither Async(completionstage<? extends T> other ,Function<? super T,U> fn);
public <UCompletableFuture<Ux applyToEither Asyne(completionstage<? extends T> other,Function<? super T,U>fn,Executor executor ) ;
public completableFuture<Void> acceptEither(completionstage<? extends T> other,Consumer<? super T> action);
public completableFuture<Void> acceptEitherAsync(completionstage<? extends T other,Consumer<? super T> action);
public comp1etab1eFuture<Void> acceptEitherAsync(completionstage<? extends T> other,Consumer<? super T> action,Executor executor);
public completableFuture<Void> runAfterEither (Completionstage<?> other ,Runnable action);
public CompletableFuture<Void> runAfterEitherAsync(Completionstage<?> other ,Runnable action);
public completableFuture<Void runAfterEither Async(Completionstage<?> other ,Runnable action,Executor executor);
当两个任务中,任意一个 future 任务完成的时候,执行任务。
(1),applyToEither:两个任务有一个执行完成,获取它的返回值,处理任务并有新的返回值。
//applyToEitherAsync感知结果,有返回值
CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务1线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("任务1结束:");
return i;
}, executor);
CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务2线程:" + Thread.currentThread().getId());
try {
Thread.sleep(3000);
System.out.println("任务2结束:");
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello";
}, executor);
CompletableFuture<String> future = future01.applyToEitherAsync(future02, res -> {
System.out.println("任务3开始。。。之前的结果:" + res);
return res.toString() + "===>很爱很爱你";
}, executor);
//获取异步任务的返回值
System.out.println("main方法结束。。。" + future.get() );
/**
* 运行结果
* main方法开始。。。
* 任务1线程:11
* 任务1结束:
* 任务3开始。。。之前的结果:5
* main方法结束。。。5===>很爱很爱你
* 任务2线程:12
*/
(2),acceptEither:两个任务有一个执行完成,获取它的返回值,处理任务,没有新的返回值。
//acceptEitherAsync:感知结果,无返回值
CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务1线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("任务1结束:");
return i;
}, executor);
CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务2线程:" + Thread.currentThread().getId());
try {
Thread.sleep(3000);
System.out.println("任务2结束:");
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello";
}, executor);
future01.acceptEitherAsync(future02,res -> {
System.out.println("任务3开始。。。之前的结果:" + res);
},executor);
//获取异步任务的返回值
System.out.println("main方法结束。。。" );
/**
* 运行结果
* main方法开始。。。
* main方法结束。。。
* 任务2线程:12
* 任务1线程:11
* 任务1结束:
* 任务3开始。。。之前的结果:5
*/
(3),runAfterEither:两个任务有一个执行完成,不需要获取 future 的结果,处理任务,也没有返 回值。
//两个任务,只要有一个完成,我们就执行任务3
//runAfterEitherAsync:不感知结果,也无返回值
CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务1线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("任务1结束:");
return i;
}, executor);
CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务2线程:" + Thread.currentThread().getId());
try {
Thread.sleep(3000);
System.out.println("任务2结束:");
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello";
}, executor);
future01.runAfterEitherAsync(future02,() -> {
System.out.println("任务3开始。。。之前的结果");
},executor);
//获取异步任务的返回值
System.out.println("main方法结束。。。" );
/**
* 运行结果
* main方法开始。。。
* 任务1线程:11
* 任务1结束:
* 任务2线程:12
* main方法结束。。。
* 任务3开始。。。之前的结果
* 任务2结束:
*/
7,多任务组合
public static completableFuture<Void>a110f(completableFuture<?>...cfs);
public static completableFuture<object> anyof(CompletableFuture<?>... cfs);
(1),allOf:等待所有任务完成 anyOf:只要有一个任务完成
CompletableFuture<String> future01 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
System.out.println("上厕所");
} catch (InterruptedException e) {
e.printStackTrace();
}
return "蹲马桶";
}, executor);
CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
System.out.println("刷抖音");
return "看小姐姐跳舞";
}, executor);
CompletableFuture<String> future03 = CompletableFuture.supplyAsync(() -> {
System.out.println("抽烟");
return "吸芙蓉王";
}, executor);
CompletableFuture<Void> allOf = CompletableFuture.allOf(future01, future02, future03);
allOf.get();//等待所有结果完成
//获取异步任务的返回值
System.out.println("main方法结束。。。" + future01.get() + future02.get() + future03.get());
/**
* 运行结果
* main方法开始。。。
* 刷抖音
* 抽烟
* 上厕所
* main方法结束。。。蹲马桶看小姐姐跳舞吸芙蓉王
*/
(2),anyOf:只要有一个任务完成
CompletableFuture<String> future01 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
System.out.println("上厕所");
} catch (InterruptedException e) {
e.printStackTrace();
}
return "蹲马桶";
}, executor);
CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
System.out.println("刷抖音");
return "看小姐姐跳舞";
}, executor);
CompletableFuture<String> future03 = CompletableFuture.supplyAsync(() -> {
System.out.println("抽烟");
return "吸芙蓉王";
}, executor);
CompletableFuture<Object> anyOf = CompletableFuture.anyOf(future01, future02, future03);
//获取异步任务的返回值
System.out.println("main方法结束。。。" + anyOf.get());
/**
* 运行结果
* main方法开始。。。
* 刷抖音
* main方法结束。。。看小姐姐跳舞
* 抽烟
*/