【问题标题】:Why CompletableFuture 's thenAccept() not running on the main thread为什么 CompletableFuture 的 thenAccept() 不在主线程上运行
【发布时间】:2016-05-02 11:32:56
【问题描述】:

我在 CompletableFuture 的 supplyAsync() 中处理长时间运行的操作,并将结果输入 thenAccept()。有时 thenAccept() 在主线程上执行,但有时它在工作线程上运行。但我只想在主线程上运行 thenAccept() 操作。这是示例代码。

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

我该如何解决这个问题?

【问题讨论】:

  • 你为什么要这么做?
  • 谢谢。假设在 thenAccept() 方法中我访问共享资源。然后我必须考虑资源的线程安全性。 Vert.x 的 executeBlocking 与此类似。他们妥善处理。
  • 好吧,“正确”可能在旁观者的眼中。如果您以异步方式访问共享资源,您似乎需要关注线程安全。也许您应该只允许通过在单个线程上安排任务的监视器访问共享资源。

标签: java completable-future


【解决方案1】:

查看CompletableFuture 的JavaDoc。有趣的部分是关于 CompletionStage 政策的部分。

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

我建议使用 thenAcceptAsync()thenRunAsync() 变体并将您的 executorService 变量传递给这两个调用。

【讨论】:

  • 所有CompletableFuture任务完成前主线程是否退出?另外,你能发布CompletableFuture javadoc 的“有趣的部分”吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-18
  • 2021-06-29
  • 2015-08-16
  • 2020-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多