业务场景
查询一个复杂接口,需要进行一些处理,比如说获取工单基本详情,获取图片信息, 标签信息,以及产品的对应物料信息,用户信息,属性信息,权限信息。那么如果是通过主线程进行处理的时候,会出现这样的场景
如果上述的查询,每个查询需要调用一个额定接口,每个接口返回数据为1秒,查询的接口为5个,那么耗时需要5秒。因为是逐步进行的,拿到返回结果才可以进行处理。
如果用空间换时间,这个情况下,异步编排就有用了,那么什么是异步编排,可以理解为启动五个线程,每个线程执行一个接口,5个线程进行处理,那么返回最长的时间也就是1秒,主线程继续执行,再进行下面的数据编排这种情况可以使用线程池进行处理
但是考虑一种情况, 一个线程进行必须先判断权限,判断权限之后,再进行查询用户,拿到用户才能获取其他的并行线程,这种逻辑处理需要关联情况,线程池就不太好用了。
结构
提供四种静态方法创建一个异步操作
创建线程
线程使用方法
k 捕获参数,v 捕获异常,抛出在当前线程,不抛出到主线程
如何捕获异步线程异常
如果有异常抛出异常或者自定义。
如何直接捕获异常
通过hande 是否有异常进行判断 重新返回
线程串行
在这里插入图片描述
package com.demo.comdemo;
import java.util.concurrent.*;
/**
* 〈功能描述〉<br>
* ----- :
*
* @date 2022/4/24 16:00
*/
public class CompletableFutureTest {
// 创建线程池
public static ExecutorService executorService = Executors.newFixedThreadPool(100);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main 线程开始");
// 接下来继续运行 不拿上个参数
CompletableFuture.supplyAsync(() -> 10).thenRun(() -> System.out.println("下来继续运行 不拿上个参数"));
// 接下来继续运行 不拿上个参数 异步
CompletableFuture.supplyAsync(() -> 10).thenRunAsync(() -> System.out.println("下来继续运行 不拿上个参数"), executorService);
// 接收上个线程参数运行 没有返回值
CompletableFuture.supplyAsync(() -> 10).thenAccept(
(k) -> System.out.println("接收上个线程参数运行 没有返回值 " + k));
// 接收上个线程参数运行 异步 没有返回值
CompletableFuture.supplyAsync(() -> 10).thenAcceptAsync(
(k) -> System.out.println("接收上个线程参数运行 没有返回值 " + k), executorService);
// 拿到A的返回值,还要在处理覆盖A的返回值
CompletableFuture.supplyAsync(() -> 10).thenApply((k) -> {
System.out.println("拿到A的返回值,还要在处理覆盖A的返回值 " + k);
return 100;
});
CompletableFuture.supplyAsync(() -> 10).thenApplyAsync((k) -> {
System.out.println("拿到A的返回值,还要在处理覆盖A的返回值 " + k);
return 100;
}, executorService);
System.out.println("main 线程结束");
}
}
任务组合
package com.demo.comdemo;
import java.util.concurrent.*;
/**
* 〈功能描述〉<br>
* ----- :
*
* @date 2022/4/24 16:00
*/
public class CompletableFutureTest {
// 创建线程池
public static ExecutorService executorService = Executors.newFixedThreadPool(100);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main 线程开始");
// 两个都完成
CompletableFuture<Integer> a = CompletableFuture.supplyAsync(() -> {
System.out.println("任务一开始");
return 1;
});
CompletableFuture<Integer> b = CompletableFuture.supplyAsync(() -> {
System.out.println("任务二开始");
return 2;
});
// a.runAfterBothAsync(b,()-> System.out.println("任务三开始"),executorService);
// a.thenAcceptBothAsync(b, (k, v) -> System.out.println("任务三开始拿到任务一参数:" + k + "拿到任务二参数" + v), executorService);
CompletableFuture<String> stringCompletableFuture = a.thenCombineAsync(b, (k, v) -> {
System.out.println("任务三开始拿到任务一参数:" + k + "拿到任务二参数" + v);
return "100";
}, executorService);
System.out.println("stringCompletableFuture = " + stringCompletableFuture.get());
// 两任务处理,不拿值 -- 不返回
// CompletableFuture.supplyAsync(() -> 10).runAfterBothAsync();
// 两任务处理 拿值 -- 不返回
// CompletableFuture.supplyAsync(() -> 10).thenAcceptBothAsync();
// // 组合 拿值 -- 返回
// CompletableFuture.supplyAsync(() -> 10).thenCombineAsync();
System.out.println("main 线程结束");
}
}
多任务组合
package com.demo.comdemo;
import java.util.concurrent.*;
/**
* 〈功能描述〉<br>
* ----- :
*
* @date 2022/4/24 16:00
*/
public class CompletableFutureTest {
// 创建线程池
public static ExecutorService executorService = Executors.newFixedThreadPool(100);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main 线程开始");
// 两个都完成
CompletableFuture<Integer> a = CompletableFuture.supplyAsync(() -> {
System.out.println("任务一开始");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务一结束");
return 1;
});
CompletableFuture<Integer> b = CompletableFuture.supplyAsync(() -> {
System.out.println("任务二开始");
System.out.println("任务二结束");
return 2;
});
//
// CompletableFuture.allOf(a,b);
// System.out.println("所有线程结束");
CompletableFuture.anyOf(b,a);
System.out.println("有一个线程结束");
Thread.sleep(2000);
System.out.println("main 线程结束");
}
}