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

为什么CompletableFuture的thenAccept()没有在主线程上运行

凌波峻
2023-03-14

我在CompletableFuture的供应Async()中处理长时间运行的操作,并将结果输入thenAccess()。在某些情况下,thenAccess()在主线程上执行,但在某些时候,它在工作线程上运行。但是我想只在主线程上运行thenAccess()操作。这是示例代码。

private void test() {

    ExecutorService executorService = Executors.newSingleThreadExecutor();

    CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {
        System.out.println("supplyAsync | I am running on : " + Thread.currentThread().getName());
        return "Hello world";
    }, executorService);

    CompletableFuture<Void> cf3 = cf1.thenAccept(s -> {
        System.out.print("thenAccept | I am running on : " + Thread.currentThread().getName());
        System.out.println(" | answer : " + s);
    });

    cf3.thenRun(() -> {
        System.out.println("thenRun | I am running on : " + Thread.currentThread().getName());
        System.out.println();
    });

}

public static void main(String[] args) {

    App app = new App();
    for(int i = 0; i < 3; i++){
        app.test();
    }
}

结果是:

supplyAsync | I am running on : pool-1-thread-1
thenAccept | I am running on : main | answer : Hello world
thenRun | I am running on : main

supplyAsync | I am running on : pool-2-thread-1
thenAccept | I am running on : main | answer : Hello world
thenRun | I am running on : main

supplyAsync | I am running on : pool-3-thread-1
thenAccept | I am running on : pool-3-thread-1 | answer : Hello world
thenRun | I am running on : pool-3-thread-1

我怎样才能解决这个问题?

共有1个答案

罗建弼
2023-03-14

看看完全未来的JavaDoc。有趣的部分是关于CompletionLevel策略的部分。

在那里,您会发现使用非异步方法会导致一种非此即彼的情况。如果您随后查看实现,您将最终进入Java运行时的非公共部分。有一些不安全的处理意味着可能会发生某种竞争条件。

我建议使用thenAcceptAsync()和thenRunAsync()变体,并将您的执行器服务变量传递给这两个调用。

 类似资料:
  • 问题内容: 我刚刚遇到了这个“错误”,但是我不确定这是否是故意的:代码: 在第一个示例中,它是在swing线程上执行的,但在第二个示例中,它不是,尽管我认为应该这样做。 这是错误还是故意的? 问题答案: 在我看来,这似乎是您的误解 第一行就像在说:“好吧,秋千,我想要你做的是”。所以Swing执行它 第二行就像是说:“确定,Swing,我要您执行的是方法返回的对象的方法”。一个是方法, 我现在执行

  • 在下面的代码中,为什么主线程要等到子线程完成。 Driver.java ThreadRunner.java 调用“t.start()”后,在驱动程序类中,程序是否应该退出?我没有使用join,但主线程仍在等待,直到新旋转的“ThreadRunner”运行开始。这是因为在java中,主线程(由main方法启动)总是等待所有线程关闭吗?

  • 问题内容: 我有这段代码: 现在,我希望能够停止执行该线程。如何阻止它执行?例如,三秒钟后,我决定不再执行该命令,因此我想停止它。 问题答案: 您可以使用s。它们可以在s 上安排,并在执行前取消。

  • 问题内容: 这是一个普遍的Java问题,而不是Android的第一个问题! 我想从二级线程的上下文中了解如何在主线程上运行代码。例如: 这类事情-我意识到我的示例有点差,因为在Java中,您不需要进入主线程即可打印出某些内容,并且Swing也具有事件队列- 但在一般情况下,您可能需要在后台线程的上下文中,在主线程上运行Runnable。 编辑:为了进行比较-这是我在Objective-C中的做法:

  • 我很难理解内部类线程的行为。 它总是打印出“main”,并且线程是按顺序执行的。为什么内部类线程的执行由主线程执行? 谢谢!

  • 我不明白为什么webclient会阻止我使用gradle的主要netty线程,以下是它的依赖项: 这个gradle脚本在两个应用程序中都使用。在第一个应用程序中,我执行: 第二个应用程序模拟长响应处理: 我希望呼叫服务不会阻塞主线程,而是会继续处理传入的连接,但直到我收到第一个呼叫的响应(睡眠将起作用),我的下一个连接将挂起等待。 结果:第一个应用程序像tomcat一样工作,只有一个线程 我的问题