Administrator
发布于 2024-08-02 / 47 阅读
0
0

CompletableFuture中allof,anyof,thenCompose,thenCombine理解

CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)

CompletableFuture 是 Java 中的一个类,它提供了一种异步编程的机制,使得你可以以声明式的方式编写异步代码。当你使用 CompletableFuture.allOf 方法时,你可以将多个 CompletableFuture 实例组合成一个单一的 CompletableFuture,这个新的 CompletableFuture 只有在所有给定的 CompletableFuture 都完成时才会完成。

如果你想要在使用 CompletableFuture.allOf 后合并它们的返回值,你可以使用 thenApplythenAccept 方法来处理所有 CompletableFuture 完成后的结果。以下是一个简单的例子:

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Result1");
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 42);
CompletableFuture<Double> future3 = CompletableFuture.supplyAsync(() -> 3.14);

CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2, future3);

CompletableFuture<Object> combinedFuture = allFutures.thenApply(v -> {
    // 当所有future都完成时,这里可以访问它们的值
    String result1 = future1.join(); // 这里使用join获取future1的结果
    Integer result2 = future2.join(); // 这里使用join获取future2的结果
    Double result3 = future3.join(); // 这里使用join获取future3的结果

    // 将结果合并为一个对象,例如一个自定义的对象或简单的数组
    return new Object[] {result1, result2, result3};
});

在这个例子中,allOf 创建了一个 CompletableFuture<Void>,它在所有给定的 CompletableFuture 都完成时完成。然后,我们使用 thenApply 来创建一个新的 CompletableFuture<Object>,它将在 allFutures 完成时执行,并返回一个包含所有结果的新对象。

请注意,join 方法会阻塞当前线程直到 CompletableFuture 完成。在实际应用中,你可能需要考虑线程安全和性能问题,以避免不必要的阻塞。此外,如果你想要处理异常,你可能需要使用 exceptionally 方法来定义异常处理逻辑。

CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)

在Java中,CompletableFuture 类的 anyOf 方法允许你将多个 CompletableFuture 实例组合成一个单一的 CompletableFuture,这个新的 CompletableFuture 会在任何一个给定的 CompletableFuture 完成时立即完成。如果你想要在使用 anyOf 之后合并返回值,你可以使用 thenApplythenAccept 方法来处理第一个完成的 CompletableFuture 的结果。

下面是一个使用 anyOf 并合并返回值的例子:

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Result1");
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 42);
CompletableFuture<Double> future3 = CompletableFuture.supplyAsync(() -> 3.14);

CompletableFuture<Object> firstCompletedFuture = CompletableFuture.anyOf(future1, future2, future3)
    .thenApplyAsync(ignored -> {
        // 这里 'ignored' 是 anyOf 完成时的参数,我们不关心它,因为我们只关心第一个完成的 future 的结果
        // 我们可以通过检查每个 future 是否完成来获取它的结果
        return CompletableFuture.anyOf(future1, future2, future3)
            .thenApply(result -> {
                // 这里 'result' 是第一个完成的 future 的结果
                if (result instanceof String) {
                    return "String result: " + result;
                } else if (result instanceof Integer) {
                    return "Integer result: " + result;
                } else if (result instanceof Double) {
                    return "Double result: " + result;
                }
                return "Unknown result type";
            });
    });

在这个例子中,我们首先使用 anyOf 来创建一个新的 CompletableFuture,它会在任何一个给定的 CompletableFuture 完成时立即完成。然后,我们使用 thenApplyAsync 来处理第一个完成的 CompletableFuture 的结果。我们通过再次使用 anyOfthenApply 来检查哪个 CompletableFuture 首先完成,并获取它的结果。

请注意,这种方法可能会导致其他未完成的 CompletableFuture 被取消,因为 anyOf 的行为是一旦任何一个 CompletableFuture 完成,其他的就会被取消。如果你想要避免这种情况,你可能需要使用其他方法来处理多个 CompletableFuture,例如使用 acceptEither 或者手动实现逻辑来检查哪个 CompletableFuture 首先完成。

<U> CompletableFuture<U> thenCompose

在Java的 CompletableFuture API中,thenCompose 方法用于将一个 CompletableFuture 的结果转换为另一个 CompletableFuture。当一个异步操作完成时,你可以使用 thenCompose 来启动另一个异步操作,并将前一个操作的结果传递给后一个操作。

thenCompose 的用法通常如下:

CompletableFuture<R> thenCompose(Function<? super T, ? extends CompletableFuture<R>> after);
T 是当前 CompletableFuture 完成时的结果类型。
R 是返回的 CompletableFuture 完成时的结果类型。
Function<? super T, ? extends CompletableFuture<R>> after 是一个函数,它接受当前 CompletableFuture 的结果作为输入,并返回一个新的 CompletableFuture<R>。

这里是一个 thenCompose 的使用示例:

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");

CompletableFuture<Integer> future2 = future1.thenCompose(s -> {
    // 当 future1 完成时,s 包含 future1 的结果
    return CompletableFuture.supplyAsync(() -> s.length()); // 将字符串长度的计算异步执行
});

在这个例子中,future1 是一个异步操作,它最终会返回字符串 "Hello"。当 future1 完成时,thenCompose 指定的函数会被调用,这个函数将 "Hello" 的长度作为一个新的结果返回。然后,这个新的结果被封装在 future2 中,它是一个计算字符串长度的异步操作。

thenCompose 有几个关键点需要注意:

  1. 错误传播:如果当前的 CompletableFuture 完成时带有异常,thenCompose 将不会执行,并且返回的 CompletableFuture 也会完成异常。

  2. 异步性thenCompose 允许你在不同的线程上异步执行操作,这有助于提高应用程序的响应性和吞吐量。

  3. 链式调用:你可以将多个 thenCompose 调用链接在一起,以创建复杂的异步操作链。

  4. 资源管理:使用 thenCompose 时,需要确保所有资源(如数据库连接、文件句柄等)在使用后都能正确关闭,以避免资源泄露。

thenCompose 是一种强大的工具,可以帮助你以声明式的方式构建复杂的异步逻辑,同时保持代码的清晰和可维护性。

<U,V> CompletableFuture<V> thenCombine(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn)

thenCombine 方法允许你将两个 CompletableFuture 的结果组合起来,并将这两个结果作为参数传递给一个函数,这个函数返回一个新的 CompletableFuture。这在你需要基于两个异步操作的结果执行某些操作时非常有用。

thenCombine 的基本用法如下:

CompletableFuture<U> thenCombine(
    CompletableFuture<? extends V> other,
    BiFunction<? super T, ? super V, ? extends U> fn);
  • other 是要与当前 CompletableFuture 结合的另一个 CompletableFuture

  • fn 是一个接受当前 CompletableFuture 的结果和 other 的结果作为参数,并返回一个新的结果的函数。

这里是一个使用 thenCombine 的示例:

CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World");

CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (i, s) -> "Number: " + i + ", Message: " + s);

在这个例子中,future1future2 是两个独立的异步操作,分别返回一个整数和一个字符串。使用 thenCombine,我们可以将这两个结果组合成一个字符串,其中包含数字和消息。

thenCombine 的关键点:

  • 错误传播:如果 future1future2 完成时带有异常,thenCombine 将传播这个异常,并且不会执行组合函数 fn

  • 顺序执行thenCombine 确保组合函数 fn 在两个 CompletableFuture 都完成后才执行。

  • 灵活性thenCombine 提供了一种灵活的方式来组合两个异步操作的结果,并基于这些结果执行进一步的处理。

使用 thenCombine 可以帮助你构建复杂的异步逻辑,同时保持代码的清晰和易于管理。


评论