1.为什么要使用这玩意
如下,现在我们这样一个场景,我们根据自己的需要查出了相关商品,然后点击某商品进去查看此商品详情
那么,我们需要如下6步进行查询,如果单纯按顺序一步步执行,那么执行时间是他们每步执行时间之和,那么此时就需要对他们进行分析,
我们点击商品时,此时我们有sku的id,很明显,前三步彼此之间没有什么影响,这时候我们可以用三个线程同时执行,而4,5,6步,又需要通过第一步
获取到他的所属spu的信息,所以是需要第一步先执行完的,那么此时我们合理的设计代码的执行逻辑就是开三个线程执行1,2,3步,等到他们最长的
那个任务执行完时,开三个线程执行4,5,6步,此时4,5,6依赖于前面1 执行的结果,像这种场景是很常见的业务场景,常用的东西到了我们这年代基本
都有了封装好的框架,此时我们就来到 CompletableFuture,他就是用来做异步编排的.
2.启动异步任务
有两种方式,一种没返回值,一种有返回值 返回值通过 get方法获取
实例如下
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
int n = 10 / 2;
System.out.println("我没返回值,Thread-" + Thread.currentThread() + "中输出:" + n);
});
Thread.sleep(100);
CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
int n = 10 / 2;
System.out.println("我有返回值,Thread-" + Thread.currentThread() + "中输出:" + n);
return n;
});
System.out.println("我的返回值是:"+integerCompletableFuture.get());
}
控制台打印结果如下:
3.完成回调与异常的感知
示例如下, whenComplete是在调用者前面任务执行完后继续执行内容,可以获取前面任务的返回结果与捕获的异常,当然异常了返回结果一般都是null,exceptionally是捕获异常并且回调方法,来返回新的结果
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
int n = 10 / 0;
System.out.println("我有返回值,Thread-" + Thread.currentThread() + "中输出:" + n);
return n;
}).whenCompleteAsync((res,exception)->{
System.out.println("res:"+res+" exception:"+exception.getMessage());
}).exceptionally((throwable)->{
return 0;
});
System.out.println("返回结果:"+integerCompletableFuture.get());
}
4.handle最终处理
有异常时:
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
int n = 10 / 0;
System.out.println("我有返回值,Thread-" + Thread.currentThread() + "中输出:" + n);
return n;
}).handle((res,exception) ->{
if(res != null){
res = res*2;
}
if(exception != null){
res = 0;
}
return res;
});
System.out.println("返回结果:"+integerCompletableFuture.get());
}
没异常时:
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
int n = 10 / 2;
System.out.println("我有返回值,Thread-" + Thread.currentThread() + "中输出:" + n);
return n;
}).handle((res,exception) ->{
if(res != null){
res = res*2;
}
if(exception != null){
res = 0;
}
return res;
});
System.out.println("返回结果:"+integerCompletableFuture.get());
}
5.线程串行化
示例没啥好写的了
6.两任务组合,都要完成
任务1,任务2都执行完后执行 的方法
示例如下,这里演示的是第一种,获取前俩任务的返回值,并且执行相关操作后返回新的值,后两种就不演示了
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Object> integerCompletableFuture1 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务一执行中...");
int n = 10 / 2;
System.out.println("任务一执行结束");
return n;
});
CompletableFuture<Object> integerCompletableFuture2 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务二执行中...");
int n = 5 / 2;
System.out.println("任务二执行结束.");
return n;
});
CompletableFuture<String> objectCompletableFuture = integerCompletableFuture1.thenCombine(integerCompletableFuture2, (r1, r2) -> {
String r3 = "";
System.out.println("任务三执行中");
r3 += r3+r1+","+r2;
System.out.println("任务三执行结束");
return r3;
});
System.out.println("任务三返回结果:"+objectCompletableFuture.get());
}
7.两任务组合,一个完成
跟上面几个方法的使用方法一样,区别就是这里是两个任务任意一个完成即可,然后执行时参数中只接收一个返回值
8. 多任务组合
get方法是阻塞式等待,一定要执行,不然无法保证所有任务全部完成才执行后面的代码
示例如下
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Object> integerCompletableFuture1 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务一查询商品图片执行中...");
System.out.println("任务一执行结束");
return "huawei121.jpg";
});
CompletableFuture<Object> integerCompletableFuture2 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务二查询商品属性执行中...");
System.out.println("任务二执行结束.");
return "256G+黑色";
});
CompletableFuture<Object> integerCompletableFuture3 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务二查询商品品牌执行中...");
System.out.println("任务二执行结束.");
return "华为";
});
CompletableFuture<Void> completableFuture = CompletableFuture.allOf(integerCompletableFuture1, integerCompletableFuture2, integerCompletableFuture3);
//此方法会阻塞式等待,直到三个方法都执行完
completableFuture.get();
System.out.println("main线程结束...");
}