1-两个任务组合,都要完成
* thenCombine:两个任务都要完成,组合两个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)
public static void main10() throws Exception {
System.out.println("main start....");
CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程1:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
}
int i = 100 / 10;
System.out.println("运行结果:" + i + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
return i;
}, executorService);
CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程2:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
String result="hello";
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
}
System.out.println("运行结果:" + result+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
return result;
}, executorService);
CompletableFuture<String> completableFuture = future01.thenCombineAsync(future02, (res1, res2) -> {
System.out.println("当前线程3:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
System.out.println("任务1结果:" + res1 + "---->任务2结果:" + res2);
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
}
return res1 + res2;
}, executorService);
System.out.println("最后返回结果:"+completableFuture.get()+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
System.out.println("main end....");
}
/**
* thenCombineAsync
* <p>
* 输出结果:
main start....
当前线程1:13->当前时间:2021-10-18 11:40:12
当前线程2:14->当前时间:2021-10-18 11:40:12
运行结果:hello->当前时间:2021-10-18 11:40:14
运行结果:10->当前时间:2021-10-18 11:40:16
当前线程3:15->当前时间:2021-10-18 11:40:16
任务1结果:10---->任务2结果:hello
最后返回结果:10hello->当前时间:2021-10-18 11:40:19
main end....
*/
* thenAcceptBoth:两个任务都要完成,组合两个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)
public static void main11() throws Exception {
System.out.println("main start....");
CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程1:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
}
int i = 100 / 10;
System.out.println("运行结果:" + i + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
return i;
}, executorService);
CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程2:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
String result="hello";
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
}
System.out.println("运行结果:" + result+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
return result;
}, executorService);
CompletableFuture<Void> completableFuture = future01.thenAcceptBothAsync(future02, (res1, res2) -> {
System.out.println("当前线程3:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
System.out.println("任务1结果:" + res1 + "---->任务2结果:" + res2);
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
}
System.out.println("任务1结果:" + res1 + "---->任务2结果:" + res2 + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}, executorService);
System.out.println("最后返回结果:"+completableFuture.get()+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
System.out.println("main end....");
}
/**
* thenAcceptBoth
* <p>
* 输出结果:
main start....
当前线程2:14->当前时间:2021-10-18 11:46:03
当前线程1:13->当前时间:2021-10-18 11:46:03
运行结果:hello->当前时间:2021-10-18 11:46:05
运行结果:10->当前时间:2021-10-18 11:46:07
当前线程3:15->当前时间:2021-10-18 11:46:07
任务1结果:10---->任务2结果:hello
任务1结果:10---->任务2结果:hello->当前时间:2021-10-18 11:46:10
最后返回结果:null->当前时间:2021-10-18 11:46:10
main end....
*/
*runAfterBoth:两个任务都要完成,组合两个future,不需要获取两个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)
public static void main12() throws Exception {
System.out.println("main start....");
CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程1:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
}
int i = 100 / 10;
System.out.println("运行结果:" + i + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
return i;
}, executorService);
CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程2:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
String result="hello";
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
}
System.out.println("运行结果:" + result+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
return result;
}, executorService);
CompletableFuture<Void> completableFuture = future01.runAfterBothAsync(future02, () -> {
System.out.println("当前线程3:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
System.out.println("不需要两个future的结果,自己执行");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
}
System.out.println("不需要两个future的结果,自己执行"+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}, executorService);
System.out.println("最后返回结果:"+completableFuture.get()+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
System.out.println("main end....");
}
/**
* runAfterBothAsync
* <p>
* 输出结果:
main start....
当前线程1:13->当前时间:2021-10-18 11:48:27
当前线程2:14->当前时间:2021-10-18 11:48:27
运行结果:hello->当前时间:2021-10-18 11:48:29
运行结果:10->当前时间:2021-10-18 11:48:31
当前线程3:15->当前时间:2021-10-18 11:48:31
不需要两个future的结果,自己执行
不需要两个future的结果,自己执行->当前时间:2021-10-18 11:48:34
最后返回结果:null->当前时间:2021-10-18 11:48:34
main end....
*/
2-两个任务组合:一个完成
public <U> CompletableFuture<U> applyToEither(CompletionStage<? extends T> other, Function<? super T, U> fn)
public <U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn)
public <U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn,Executor executor)
public static void main13() throws Exception {
System.out.println("main start....");
CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程1:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
}
int i = 100 / 10;
System.out.println("运行结果:" + i + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
return i;
}, executorService);
CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程2:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
String result="hello";
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
}
System.out.println("运行结果:" + result+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
return result;
}, executorService);
CompletableFuture<String> completableFuture = future01.applyToEitherAsync(future02, (res) -> {
System.out.println("当前线程3:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
//这里两个future返回值类型必须一致,否则不知道用哪个
System.out.println("两个future的任意一个的结果,res=" + res);
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
}
System.out.println("两个future的任意一个的结果,res=" + res + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
return "world:" + res;
}, executorService);
System.out.println("最后返回结果:"+completableFuture.get()+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
System.out.println("main end....");
}
* applyToEitherAsync
* <p>
* 输出结果:
main start....
当前线程2:14->当前时间:2021-10-18 13:49:38
当前线程1:13->当前时间:2021-10-18 13:49:38
运行结果:hello->当前时间:2021-10-18 13:49:40
当前线程3:15->当前时间:2021-10-18 13:49:40
两个future的任意一个的结果,res=hello
运行结果:10->当前时间:2021-10-18 13:49:42
两个future的任意一个的结果,res=hello->当前时间:2021-10-18 13:49:43
最后返回结果:world:hello->当前时间:2021-10-18 13:49:43
main end....
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 CompletableFuture<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> runAfterEitherAsync(CompletionStage<?> other,Runnable action,Executor executor)
3-多任务组合
*allOf:等待所有任务完成
*anyOf:只要有一个任务完成
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
ps:allOf方法使用场景:比如电商系统中商品详情页,三个查询:查询商品图片,查询商品属性,查询商品描述;可以分解三个查询,同时查询,最后等待三个查询完成得到结果
public static void main14() throws Exception {
System.out.println("main start....");
CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程1:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
}
int i = 100 / 10;
System.out.println("运行结果:" + i + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
return i;
}, executorService);
CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程2:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
String result="hello";
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
}
System.out.println("运行结果:" + result+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
return result;
}, executorService);
CompletableFuture<Void> completableFuture = CompletableFuture.allOf(future01,future02);
completableFuture.get();
System.out.println("最后返回结果"+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
System.out.println("main end....");
}
/**
*
* <p>
* 输出结果:
*
main start....
当前线程1:13->当前时间:2021-10-18 14:18:38
当前线程2:14->当前时间:2021-10-18 14:18:38
运行结果:hello->当前时间:2021-10-18 14:18:40
运行结果:10->当前时间:2021-10-18 14:18:42
最后返回结果->当前时间:2021-10-18 14:18:42
main end....
*/
4-CompletionService
CompletionService的实现原理是内部维护了一个阻塞队列,当任务执行结束就把任务的执行结果加入到阻塞队列中。
public static void main16() throws Exception {
System.out.println("main start...."+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
CompletionService<String> completionService = new ExecutorCompletionService<>(executorService);
for(int i=1;i<=3;i++){
final int j=i;
completionService.submit(() -> {
System.out.println("线程:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"第几次:"+j);
String shopInfo = getShopInfo(j);
return shopInfo;
});
}
for(int i=1;i<=3;i++){
try{
System.out.println( "执行->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
String res = completionService.take().get(6L,TimeUnit.SECONDS);
System.out.println("获取结果线程:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"第几次:"+i+"获取值为:"+res);
}catch(Exception e){
System.out.println("获取结果线程error:" + Thread.currentThread().getId() + "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"第几次:"+i+"获取值为000");
}
}
System.out.println("main end...."+ "->当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
public static String getShopInfo(int i) throws Exception{
if(i==1){
TimeUnit.SECONDS.sleep(5);
return "A";
}
if(i==2){
TimeUnit.SECONDS.sleep(8);
int aa=10/0;
return "B";
}
if(i==3){
TimeUnit.SECONDS.sleep(4);
return "C";
}
return "D";
}
/**
* CompletionService 应用场景
* 比如我们平台【医药平台】 需要去每个药店A.B.C查询结果,
* 如果串行化,比如A药店需要5秒;B药店需要8秒;C药店需要4秒,那么系统一共5+8+4=17秒
* 如果并行化,那么最多就是8秒;
*
* 如果我们进一步优化,比如要求7秒内有结果,还可以设置获取值是7秒时间【通过http请求设置超时时间】,丢弃B药店8秒
*
*
*main start....->当前时间:2021-10-18 14:49:13
* 执行->当前时间:2021-10-18 14:49:13
* 线程:13->当前时间:2021-10-18 14:49:13第几次:1
* 线程:15->当前时间:2021-10-18 14:49:13第几次:3
* 线程:14->当前时间:2021-10-18 14:49:13第几次:2
* 获取结果线程:1->当前时间:2021-10-18 14:49:17第几次:1获取值为:C
* 执行->当前时间:2021-10-18 14:49:17
* 获取结果线程:1->当前时间:2021-10-18 14:49:18第几次:2获取值为:A
* 执行->当前时间:2021-10-18 14:49:18
* 获取结果线程error:1->当前时间:2021-10-18 14:49:21第几次:3获取值为000
* main end....->当前时间:2021-10-18 14:49:21
*
*/