简记-CompletableFuture异步编排

98 阅读2分钟

在一些数据处理业务模块中,例如报表接口,我们需要多方取数,汇总多个指标。随着数据量的增多,可以使用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()避免异常发生造成主线程阻塞等待