本文介绍了为什么CompletableFuture的thenAccept()无法在主线程上运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I process the long running operation inside the CompletableFuture's supplyAsync() and get the result into thenAccept(). In some times thenAccept() perform on the main thread but some time it running on the worker thread.But I want run thenAccept() operation only on the main thread. this is the sample code.

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

我该如何解决?

推荐答案

在。有趣的部分是有关 CompletionStage 策略的部分。

Take a look in the JavaDoc of CompletableFuture. The interesting part is the one about the CompletionStage policies.

在那里,您发现使用 non-async 方法导致一种或非场景。然后,如果您看一下实现,您将最终遇到Java Runtime的非公开部分。有一些 UNSAFE 处理意味着可能发生某种竞争情况。

There you find that using the non-async method results in a kind of either-or-scenario. If you then take a look in the implementation you will end up in the non-public part of the Java Runtime. There is some UNSAFE handling that implies that there may happen some kind of race condition.

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

I would suggest using thenAcceptAsync() and thenRunAsync() variants and pass your executorService variable to both calls.

这篇关于为什么CompletableFuture的thenAccept()无法在主线程上运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-22 20:33
查看更多