CompletableFuture可以进行异步调用,类似于js在的Promise
ExecutorService executorService = Executors.newFixedThreadPool(10);//线程池,一般放在静态成员变量中
CompletableFuture<Integer> exceptionally = CompletableFuture.supplyAsync(() -> {
//返回一个数据
return 1;
},executorService).whenComplete((res, throwable) -> {
//完成异步时获取返回值
System.out.println("返回值是:"+res+",异常是:"+throwable);
}).exceptionally((throwable) -> {
//接收异常,修改返回值
System.out.println("获得到的异常是:"+throwable);
return 10;//返回一个值替代原来的返回值
});
感知返回值,接收异常,并修改返回值
上面的方式通过whenComplete方法
感知结果的产生,并且能接收异常,但是不能修改返回值,如果要修改返回值,就得和上面的案例一样结合exceptionally方法
才能达到效果。
handle方法
ExecutorService executorService = Executors.newFixedThreadPool(10);//线程池,一般放在静态成员变量中
CompletableFuture<Integer> exceptionally = CompletableFuture.supplyAsync(() -> {
//返回一个数据
return 1;
},executorService).handle((res,throwable)->{
if (res==1){
System.out.println("返回的结果是"+res);
return 1;
}
if (throwable!=null){
System.out.println("异常是"+throwable);
return 0;
}
return 100;
});
runAfterBoth
方法无法感知任务一
和任务二
是否完成
ExecutorService executorService = Executors.newFixedThreadPool(10);//线程池,一般放在静态成员变量中
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务一开始");
return 1;
},executorService);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务二开始");
return 2;
},executorService);
future1.runAfterBothAsync(future2,()->{
System.out.println("联合任务1和2");
},executorService);
使用thenAcceptBothAsync
会感知任务一和任务二都完成。
ExecutorService executorService = Executors.newFixedThreadPool(10);//线程池,一般放在静态成员变量中
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务一开始");
return 1;
},executorService);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务二开始");
return 2;
},executorService);
future1.thenAcceptBothAsync(future2,(result1,result2)->{
System.out.println("感知任务一和任务二完成,执行任务三");
},executorService);
合并多个任务使用thenCombineAsync
在上面的结果,基础上,如果想要有返回值则使用它
ExecutorService executorService = Executors.newFixedThreadPool(10);//线程池
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务一开始");
return 1;
},executorService);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务二开始");
return 2;
});
future1.thenCombineAsync(future2,(res1,res2)->{
System.out.println("感知任务完成,合并两个任务,返回一个新的结果");
return res1+","+res2;
},executorService);
两个任务只要有一个完成就执行任务三的方法都是 XXXEither
都带有Either
runAfterEitherAsync
:不感知结果,并且无返回值
ExecutorService executorService = Executors.newFixedThreadPool(10);//线程池
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务一开始");
try {
TimeUnit.MILLISECONDS.sleep(200);//让任务二晚点执行完,等任务二完成,任务三就会开始
} catch (InterruptedException e) {
e.printStackTrace();
}
return 1;
},executorService);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务二开始");
return 2;
});
future1.runAfterEitherAsync(future2,()->{
System.out.println("任务三开始,任务一任务二只要有一个完成就会开始执行任务三");
},executorService);
acceptEitherAsync
:感知结果,接收返回值并消费掉,不产生返回值
ExecutorService executorService = Executors.newFixedThreadPool(10);//线程池
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务一开始");
try {
TimeUnit.MILLISECONDS.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 1;
},executorService);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务二开始");
return 2;
});
future1.acceptEitherAsync(future2,(res)->{
System.out.println("感知结果执行任务三");//需要注意使用lambda表达式需要future1和future2返回值类型相同
},executorService);
applyToEitherAsync
:感知返回值,转换返回值得到一个新的结果
ExecutorService executorService = Executors.newFixedThreadPool(10);//线程池
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务一开始");
try {
TimeUnit.MILLISECONDS.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 1;
},executorService);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务二开始");
return 2;
});
future1.applyToEitherAsync(future2,(res)->{
System.out.println("感知结果执行任务三");//需要注意使用lambda表达式需要future1和future2返回值类型相同
return "新的返回值"+res*2;
},executorService);
allOf
方法
如果使用下面的代码等待多任务完成。
问题一:是执行future1.get();
时线程是堵塞的,因此future2.get();future3.get();
都不能执行,这样会导致执行的时间不会是三个任务最大的时间,而是加上了多余堵塞的时间。
问题二:就是产生冗余代码
future1.get();
future2.get();
future3.get();
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务一开始");
return 1;
},executorService);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务二开始");
return 2;
});
CompletableFuture<Integer> future3 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务三开始");
return 3;
}, executorService);
CompletableFuture<Void> allOf = CompletableFuture.allOf(future1, future2, future3);
try {
allOf.get();//等待所有任务都完成
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
如果要获得每一个任务的返回结果还是需要使用future1.get();
,future2.get()
,future3.get()
得到返回结果。
anyOf
ExecutorService executorService = Executors.newFixedThreadPool(10);//线程池
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务一开始");
return 1;
}, executorService);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务二开始");
return 2;
});
CompletableFuture<Integer> future3 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务三开始");
return 3;
}, executorService);
CompletableFuture<Object> anyOf = CompletableFuture.anyOf(future1, future2, future3);
try {
anyOf.get();//获得完成的那个任务结果,其它任务的结果就获取不到,想要获取得调用各自得get
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}