一个基于CompletableFuture的异步任务获取数据并拿到返回值的小demo,希望有更好的办法,目前留作自用。
使用线程去异步获取不同渠道的数据,并且拿到每个线程的返回值。
待解决问题:某一个线程过长时间没有拿到返回值问题。
// 定义渠道
private static final String[] tenantName = {"美团", "饿了吗", "京东到家", "阿斯尔顿"};
// 线程池
private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(
5, 8, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(50), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
假装去其他渠道获取数据
// 模拟 根据渠道查询数据
private static String feginQueryByTenantId(String tenantId) throws InterruptedException {
Thread.sleep(2000); // 假装查询两秒
return tenantId + "查询完毕";
}
方法一
// 根据渠道集合查询数据 方法一
private static List<String> function_1(){
CopyOnWriteArrayList<FutureTask<String>> futureTaskArrayList = new CopyOnWriteArrayList<>();
// 遍历渠道id或者渠道唯一标识
Arrays.stream(tenantName).forEach(name -> {
FutureTask<String> futureTask = new FutureTask<>(() -> {
// 此处写根据渠道查询业务的方法, 比如内部返回值之类的
Thread.sleep(2000);
return name + "OK";
});
executor.submit(futureTask);
futureTaskArrayList.add(futureTask);
});
// "美团", "饿了吗", "京东到家", "阿斯尔顿" 所有品牌返回的数据集合
return futureTaskArrayList.stream().map(task -> {
try {
// 获取futureTask里边的返回值
// 注意,get方法是阻塞的,如果该线程返回值没有返回,则会等待到返回后,再继续get下一个线程
return task.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
return null;
}).collect(Collectors.toList());
}
方法二
// 方式二, 利用CompletableFuture查询多渠道
private static List<String> function_2(){
// 存放各个渠道将要查询的任务
CopyOnWriteArrayList<CompletableFuture<String>> futureTaskArrayList = new CopyOnWriteArrayList<>();
Arrays.stream(tenantName).forEach(tenant -> {
// supplyAsync 异步查询
CompletableFuture<String> stringCompletableFuture = CompletableFuture.supplyAsync(() -> {
try {
// 调用feign接口查询不同渠道
return feginQueryByTenantId(tenant);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
});
futureTaskArrayList.add(stringCompletableFuture);
});
// 将任务List转换成数组
CompletableFuture[] completableFutures = futureTaskArrayList.toArray(new CompletableFuture[futureTaskArrayList.size()]);
// 把任务数组放入 CompletableFuture 内. // allOf代表必须等所有任务都返回后才继续, anyOf代表只要有一个任务返回数据,就直接下一步,不等别的了
CompletableFuture<Void> allCompletableFuture = CompletableFuture.allOf(completableFutures);
// 返回所有渠道的数据,并拼装一块
List<String> join = allCompletableFuture.thenApply(e -> futureTaskArrayList.stream().map(CompletableFuture::join).collect(Collectors.toList())).join();
return join;
}