解决问题:是在复杂的义务里面,拆分为多线程使用异步编排执行对应的业务,提高响应速度
一、创建异步对象
1.CompletableFuture
提供了四个静态方法来创建一个异步操作
![](https://i-blog.csdnimg.cn/blog_migrate/9fe36b942f7df9936d02d40a128dde4b.png)
runXxxx
都是没有返回结果的,
supplyXxx
都是可以获取返回结果的
可以传入自定义的线程池,否则就用默认的线程池;
runAsync:
CompletableFuture.runAsync(()->{
System.out.println("当前线程:"+Thread.currentThread().getId());
int i=10/2;
System.out.println("运行的结果"+i);
},executor);
supplyAsync:
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 0;
System.out.println("运行的结果" + i);
return i;
}, executor);
二、计算完成时回调方法
whenComplete
可以处理正常和异常的计算结果,
exceptionally
处理异常情况。
whenComplete
和
whenCompleteAsync 的区别:
whenComplete:是执行当前任务的线程执行继续执行
whenComplete
的任务。
whenCompleteAsync:是执行把
whenCompleteAsync
这个任务继续提交给线程池
来进行执行。
* 方法完成后的感知
*/
// CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
// System.out.println("当前线程:" + Thread.currentThread().getId());
// int i = 10 / 0;
// System.out.println("运行的结果" + i);
// return i;
// }, executor).whenComplete((res,excption)->{
// //能感知异常信息,但是没法修改返回数据
// System.out.println("异步任务成功完成了....结果是:"+res+";异常是:"+excption);
// }).exceptionally(throwable -> {
// //可以感知异常,同时返回默认值
// return 10;
// });
三、
handle
方法
![](https://i-blog.csdnimg.cn/blog_migrate/94ddd2bf66b35800b27475354df9b8d5.png)
和
complete
一样,可对结果做最后的处理(可处理异常),可改变返回值。
/**
* 方法完成后的处理
*/
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("运行的结果" + i);
return i;
}, executor).handle((res,exc)->{
if(res!=null){
return res*2;
}
if(exc!=null){
return 0;
}
return 1;
});
四、线程串行化方法
![](https://i-blog.csdnimg.cn/blog_migrate/0c54cd9587cd0881f7074cda45a4f696.png)
/** *线程串行化 * 1、thenRun:不能获取到上一步的执行结果 * 2、thenAcceptAsync能接受上一步结果,但是无返回值 * 3、thenApplyAsync能接受上一步结果,有返回值 */
thenRun
方法:只要上面的任务执行完成,就开始执行
thenRun
,只是处理完任务后,执行
thenRun
的后续操作
CompletableFuture<String> future = 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);
thenApply
方法:当一个线程依赖另一个线程时,获取上一个任务返回的结果,并返回当前
任务的返回值。
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("运行的结果" + i);
return i;
}, executor).thenApplyAsync(res -> {
System.out.println("运行的结果" + res);
return "hello" + res;
}, executor);
五、两任务组合
-
都要完成
![](https://i-blog.csdnimg.cn/blog_migrate/8a2aaa8de76fd72bf5908a06b29c8f69.png)
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 "hellow";
}, executor);
两个任务必须都完成,触发该任务。
runAfterBoth
:组合两个
future
,不需要获取
future
的结果,只需两个
future
处理完任务后,
处理该任务。
future01.runAfterBothAsync(future02,()->{
System.out.println("任务3开始。。。。");
},executor);
thenAcceptBoth
:组合两个
future
,获取两个
future
任务的返回结果,然后处理任务,没有
返回值。
future01.thenAcceptBothAsync(future02,(f1,f2)->{
System.out.println("任务3开始。。。。之前的结果:"+f1+"==>"+f2);
},executor);
thenCombine
:组合两个
future
,获取两个
future
的返回结果,并返回当前任务的返回值
CompletableFuture<String> future = future01.thenCombineAsync(future02, (f1, f2) -> {
return f1 + ":" + f2 + "-->haha";
}, executor);
六、两任务组合
-
一个完成
![](https://i-blog.csdnimg.cn/blog_migrate/268224212d5e475745e7bd5bd1613c0f.png)
当两个任务中,任意一个
future
任务完成的时候,执行任务。
/** * 两个任务,只要有一个完成,我们就执行任务3 * runAfterEitherAsync:不感知结果,自己不返回值 * acceptEitherAsync: 感知结果,自己不返回值 * applyToEitherAsync :感知结果,有返回值 */
runAfterEither
:两个任务有一个执行完成,不需要获取
future
的结果,处理任务,也没有返
回值。
future01.runAfterEitherAsync(future02,()->{
System.out.println("任务3开始。。");
},executor);
acceptEither
:两个任务有一个执行完成,获取它的返回值,处理任务,没有新的返回值。
future01.acceptEitherAsync(future02,(res)->{
System.out.println("任务3开始。。"+res);
},executor);
applyToEither
:两个任务有一个执行完成,获取它的返回值,处理任务并有新的返回值。
CompletableFuture<String> future = future01.applyToEitherAsync(future02, res -> {
System.out.println("任务3开始。。"+res);
return res.toString() + "_哈哈";
}, executor);
System.out.println("main---end"+future.get());
7
、多任务组合
![](https://i-blog.csdnimg.cn/blog_migrate/dd574b40de945d4a555367a13a05ee02.png)
CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {
System.out.println("查询商品的图片信息");
return "hello.jpg";
},executor);
CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {
System.out.println("查询商品的属性");
return "黑色+256";
},executor);
CompletableFuture<String> futureDesc = CompletableFuture.supplyAsync(() -> {
System.out.println("查询商品的介绍");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "华为";
},executor);
allOf
:等待所有任务完成
CompletableFuture<Void> allOf = CompletableFuture.allOf(futureImg, futureDesc, futureAttr);
allOf.get();
System.out.println("main---end"+futureImg.get()+"="+futureDesc.get()+"="+futureAttr.get());
anyOf
:只要有一个任务完成
CompletableFuture<Object> anyOf = CompletableFuture.anyOf(futureImg, futureDesc, futureAttr);
anyOf.get();//等待所有结果完成
System.out.println("main---end"+anyOf.get());
总结:异步,方法有三个特性
1、方法处理自身业务,不接受到前面传递的值,不返回值
2、方法处理自身业务,接受前面传递的值,不返回值
3、方法处理自身业务,接受前面传递的值,返回值