当前位置: 首页 > 知识库问答 >
问题:

CompletableFuture、SupplySync()和Apply()

邢臻
2023-03-14

需要确认一些事情。以下代码:

CompletableFuture
    .supplyAsync(() -> {return doSomethingAndReturnA();})
    .thenApply(a -> convertToB(a));

将与以下相同:

CompletableFuture
    .supplyAsync(() -> {
        A a = doSomethingAndReturnA();
        convertToB(a);
 });

右?

此外,接下来的另外两个问题是“我们有什么理由使用 thenApply

1) 有转换的大代码吗?

2)需要在其他地方重用lambda块?

共有2个答案

翟卓君
2023-03-14

thenApply() 是一个回调函数,当 supplyAsync() 返回一个值时,将执行该函数。

在代码片段2中,调用< code > doSomethingAndReturnA()的线程等待函数执行并返回数据

但是在一些异常情况下(比如调用Webservice和等待响应),线程需要等待很长时间才能得到响应,这严重消耗了大量的系统计算资源(仅仅是等待响应)。

为了避免这种情况,CompletableFuture带有回调功能,一旦调用doThingAndRecnA(),一个单独的线程将负责执行doThingAndRecnA(),并且主调用者线程将继续执行其他操作,而无需等待响应返回。

一旦doThingAndRecnA的响应可用,将调用回调方法(即thenApply()

庄智
2023-03-14

这不是一回事。在第二个示例中,如果不使用<code>thenappy

但是,在第一个示例中,当使用< code>thenApply方法时,可能会发生其他情况。

首先,如果执行<code>doSomething和Returna<code>的<code>CompletableFuture</code>已经完成,调用<code>然后应用<code>将在调用线程中发生。如果<code>CompletableFutures

困惑?这篇文章可能会有所帮助(感谢@SotiriosDimanolis的链接)。

我提供了一个简短的例子来说明thenApply是如何工作的。

public class CompletableTest {
    public static void main(String... args) throws ExecutionException, InterruptedException {
        final CompletableFuture<Integer> future = CompletableFuture
                .supplyAsync(() -> doSomethingAndReturnA())
                .thenApply(a -> convertToB(a));

        future.get();
    }

    private static int convertToB(final String a) {
        System.out.println("convertToB: " + Thread.currentThread().getName());
        return Integer.parseInt(a);
    }

    private static String doSomethingAndReturnA() {
        System.out.println("doSomethingAndReturnA: " + Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return "1";
    }
}

输出为:

doSomethingAndReturnA: ForkJoinPool.commonPool-worker-1
convertToB: ForkJoinPool.commonPool-worker-1

因此,当第一个操作很慢时(即CompletableFuture尚未完成),两个调用都发生在同一个线程中。但是如果我们要删除<code>线程。sleep-从<code>DoSomething和Returna</code>调用输出(可能)如下:

doSomethingAndReturnA: ForkJoinPool.commonPool-worker-1
convertToB: main

请注意,转换ToB调用位于main线程中。

 类似资料:
  • 我正在java8中尝试: 运行时,我得到以下输出: 是否需要“错误”信息?我的代码片段中有没有遗漏什么?

  • 要并行或异步运行一些东西,我可以使用ExecutorService:

  • 我正在实施重试策略。基本上,我想做的是在一个单独的线程上重试POST请求。我在用杰曼的故障保护(https://github.com/jhalterman/failsafe#asynchronous-api集成)这是我的代码 我不想抓住这里的例外。它由重试策略处理。目前不会重试,因为我在这里捕获了异常。是否有方法从“SupplySync”引发异常,以便由重试策略处理?谢谢谢谢

  • 我正在尝试实现一个通用的REST客户端,如下所示。我有自己的模型将HTTP响应表示为response T。这里T是服务调用的返回类型,它可能只是T或Ts列表。下面的代码不编译,我需要帮助。 最终调用下面的方法,

  • 在Java 8中引入了CompletableFuture类来表示Future,可以通过设置其值和状态明确来完成。 它可以用作java.util.concurrent.CompletionStage。 它支持在未来完成时触发的依赖功能和操作。 在java 9中,CompletableFuture API得到了进一步的增强。 以下是对API进行的相关更改。 支持延迟和超时。 Improved supp

  • 问题内容: 我刚刚开始探索Java 8的一些并发特性。让我有些困惑的是这两个静态方法: 有谁知道为什么选择使用界面供应商?使用Callable是否更自然,这类似于Runnable返回值?那是因为供应商没有抛出无法处理的异常吗? 问题答案: 简短答案 不,用代替in 是不自然的。该论点几乎完全是关于语义的,因此,如果您此后仍不确信,那就可以了。 长答案 的和功能接口/ SAM类型在功能几乎等同(原谅