根据B站系列视频总结
【Java并发·05】CompletableFuture扩展_哔哩哔哩_bilibili
java8中的新特性,为JAVA异步编程提供了可能性。异步意味着任务可以单独运行在其他线程中,并通过回调可以在主线程中得到异步任务的执行状态。
public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
//实现了Future接口就可以兼容现在有线程池框架
//CompletionStage接口才是异步编程的接口抽象,里面定义多种异步方法
初体验**supplyAsync()
** 开启异步任务
class Solution {
public static void sleepMillis(long millis){
try {
Thread.sleep(millis);
}catch (InterruptedException e){
e.printStackTrace();
}
}
public static void printTimeAndThread(String tag){
String result=new StringJoiner("\t|\t")
.add(String.valueOf(System.currentTimeMillis()))
.add(String.valueOf(Thread.currentThread().getId()))
.add(Thread.currentThread().getName())
.add(tag)
.toString();
System.out.println(result);
}
public static void main(String[] args) {
Solution.printTimeAndThread("小白进入餐厅");
Solution.printTimeAndThread("点了一盘菜+一碗饭");
CompletableFuture<String> other=CompletableFuture.supplyAsync(
()->{
Solution.printTimeAndThread("厨师炒菜");
Solution.sleepMillis(200);
Solution.printTimeAndThread("厨师盛饭");
return "饭菜好了";
}
);
Solution.printTimeAndThread("小白打游戏");
Solution.printTimeAndThread(other.join());
Solution.printTimeAndThread("吃饭");
}
}
打印结果:
1658801729041 | 1 | main | 小白进入餐厅
1658801729041 | 1 | main | 点了一盘菜+一碗饭
1658801729103 | 1 | main | 小白打游戏
1658801729103 | 11 | ForkJoinPool.commonPool-worker-1 | 厨师炒菜
1658801729316 | 11 | ForkJoinPool.commonPool-worker-1 | 厨师盛饭
1658801729316 | 1 | main | 饭菜好了
1658801729316 | 1 | main | 吃饭
如果有多个任务,可以在 CompletableFuture内再用一个CompletableFuture.supplyAsync()。但是CompletableFuture提供了更方便的方法**thenCompose()
**。thenCompose()
将两个异步任务连接,这两个异步计算之间相互独立,同时第二个又依赖于第一个的结果。
public static void main(String[] args) {
Solution.printTimeAndThread("小白进入餐厅");
Solution.printTimeAndThread("点了一盘菜+一碗饭");
CompletableFuture<String> other=CompletableFuture.supplyAsync(
()->{
Solution.printTimeAndThread("厨师炒菜");
Solution.sleepMillis(200);
return "菜好了"; //return传到dish里
}).thenCompose(dish->CompletableFuture.supplyAsync(()->{
Solution.printTimeAndThread("服务员盛饭");
Solution.sleepMillis(100);
return dish+"饭好了";
}));
Solution.printTimeAndThread("小白打游戏");
Solution.printTimeAndThread(other.join());
Solution.printTimeAndThread("吃饭");
}
//打印结果:
1658801935231 | 1 | main | 小白进入餐厅
1658801935232 | 1 | main | 点了一盘菜+一碗饭
1658801935300 | 11 | ForkJoinPool.commonPool-worker-1 | 厨师炒菜
1658801935301 | 1 | main | 小白打游戏
1658801935512 | 11 | ForkJoinPool.commonPool-worker-1 | 服务员盛饭
1658801935626 | 1 | main | 菜好了饭好了
1658801935626 | 1 | main | 吃饭
**thenCombine()
**合并两个没有依赖关系的CompletableFutures任务。两个任务执行完后,根据两个结果,可以转为一个结果。两个输入一个输出。类似的函数还有thenAcceptBoth()
得到前两个任务的结果后没有返回值。runAfterBoth()
**thenApply()
**将上一步异步的结果交给后面的funcion.这两个任务是在一个线程中,同步的.一个接收参数一个返回参数。类似的还有thenAccept()
会接收前面的参数,但没有返回值。thenRun()
不会接收前面的参数且没有返回值
**thenApplyAysn()
**将上一步异步的结果交给后面的funcion,异步的。相当于thenCompose()
**applyToEither()
**两个运行任务,哪个任务先运行完就将结果给function
exceptionally()
可以加在链式操作的任意部分,用于处理异常.类似的方法有handle()
参数是BiFunction,无论正常执行还是有异常,handle方法都会返回一个结果。whenComplete()
方法和handle()类似,但没有返回值。
.exceptionally(e->{
Solution.printTimeAndThread(e.getMessage());
return "处理异常";
})
CompletableFuture的方法有很多是以下形式
xxx(arg)
xxxAsync(arg)
xxxAsync(arg,Executor)
以thenApply()为例:会将两块代码封装成一个任务交给一个线程运行