在一些数据处理业务模块中,例如报表接口,我们需要多方取数,汇总多个指标。随着数据量的增多,可以使用CompletableFuture类对业务逻辑进行异步编排,加快处理速度。
CountDownLatch countDownLatch = new CountDownLatch(3);
// sku数据
CompletableFuture<Map<String, List<GnPlusStoreSku>>> skuGroupFuture = CompletableFuture.supplyAsync(() -> {
Map<String, List<GnPlusStoreSku>> skuGroup = new HashMap<>();
try {
skuGroup = buildSkuGroup(gnIds);
} catch (BusinessException e) {
//do something
} finally {
countDownLatch.countDown();
}
return skuGroup;
},marketExecutor);
// 提货时间
CompletableFuture<Map<String, Set<String>>> takeTimeSetFuture = CompletableFuture.supplyAsync(() -> {
Map<String, Set<String>> takeTimeSet = new HashMap<>();
try {
takeTimeSet = buildTakeTimeSet(gnIds);
} catch (BusinessException e) {
//do something
} finally {
countDownLatch.countDown();
}
return takeTimeSet;
},marketExecutor);
// 门店数据
CompletableFuture<Map<String, List<BaseActivityStore>>> storeMapFuture = CompletableFuture.supplyAsync(() -> {
Map<String, List<BaseActivityStore>> storeMap = new HashMap<>();
try {
storeMap = buildStoreMap(gnIds);
} catch (BusinessException e) {
//do something
} finally {
countDownLatch.countDown();
}
return storeMap;
},marketExecutor);
// 等待所有异步任务执行完成
try {
countDownLatch.await();
} catch (InterruptedException e) {
//do something
}
// 获取异步任务的结果
Map<String, List<GnPlusStoreSku>> skuGroup = skuGroupFuture.join();
Map<String, Set<String>> takeTimeSet = takeTimeSetFuture.join();
Map<String, List<BaseActivityStore>> storeMap = storeMapFuture.join();
//汇总逻辑...
CountDownLatch一般与CompletableFuture连用。
CountDownLatch 是一个同步辅助类,允许一个或多个线程等待一组操作完成。
CompletableFuture 提供了多种方法来处理异步操作,以下是三个常用方法的详细解释:
1. CompletableFuture.supplyAsync(Supplier supplier)
这个方法用于创建一个异步的 CompletableFuture 实例,它将在后台线程中执行提供的 Supplier 函数,并在计算完成时返回结果。这个方法非常适合用于启动一个长时间运行的异步任务,而不会阻塞当前线程。
示例:
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
// 模拟一个耗时的操作
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return "Hello, Async World!";
});
2. CompletableFuture.thenApply(Function function)
thenApply 方法用于对 CompletableFuture 完成后的结果进行处理。它接受一个 Function 作为参数,当 CompletableFuture 完成时,会将 Function 应用于结果,并返回一个新的 CompletableFuture,其结果为 Function 的返回值。
示例:
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello, World!")
.thenApply(s -> s.toUpperCase()); // 将字符串转换为大写
在这个示例中,原始的 CompletableFuture 完成后,thenApply 方法将字符串 "Hello, World!" 转换为大写 "HELLO, WORLD!"。
3. CompletableFuture.get()
get 方法用于从 CompletableFuture 实例中获取结果。这个方法是阻塞的,它会等待异步操作完成,然后返回结果。如果 CompletableFuture 由于异常而完成,get 方法会抛出 ExecutionException,如果当前线程在等待期间被中断,则会抛出 InterruptedException。
示例:
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
// 模拟耗时操作
return "Hello, World!";
});
try {
String result = future.get(); // 阻塞直到异步操作完成
System.out.println(result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
在这个示例中,get 方法被用来等待异步操作的完成并获取结果。如果异步操作在一秒钟后成功完成,get 方法将返回 "Hello, World!"。
这些方法可以组合使用,创建复杂的异步操作链,允许开发者以声明式的方式处理异步编程。
4.注意事项
需要在finally{}中使用countDownLatch.countDown()避免异常发生造成主线程阻塞等待