简体   繁体   English

如果手动完成,则不会调用 CompletableFuture 回调

[英]CompletableFuture callback not called if completed manually

In this basic example of CompletableFuture , I run a task asynchronously and when it's finished, an async callback should be triggered.CompletableFuture的这个基本示例中,我异步运行了一个任务,当它完成时,应该触发一个异步回调。

One second after I start running the task, and before it's finished, I complete it.在我开始运行任务后一秒钟,在它完成之前,我完成了它。 After that I don't see it running the asynchronous callback anymore.之后,我不再看到它运行异步回调。

public static void main(String[] args) throws InterruptedException {
    runTask();
    Thread.sleep(1000);
    completableFuture.complete("Test");
    Thread.sleep(4000);
}

public static void runTask() {
    completableFuture = CompletableFuture.supplyAsync(() -> {
        System.out.println("Running...");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("...finished");
        return "finished task";
    })
    .thenApplyAsync(s -> {
        System.out.println("Apply on result: " + s);
        return "Result: " + s;
    })
}

The result of this is:结果是:

Running...
...finished

The thing is that if I add another callback, then it runs the first one but not the second one.问题是,如果我添加另一个回调,那么它会运行第一个而不是第二个。

.thenApplyAsync(s -> {
    System.out.println("Second apply with result: " + s);
    return "Result: " + s;
})

Then the result is:那么结果是:

Running...
...finished
Apply on result: finished task

Reading the documentation I understood all the callbacks would be always called, even if the future is completed manually.阅读文档后,我了解到所有回调都会被调用,即使未来是手动完成的。 Am I missing something here?我在这里错过了什么吗?

I guess if you write it slightly differently, it should make some sense:我想如果你写得稍微不同,它应该是有道理的:

public static void runTask() {

    CompletableFuture<String> one = CompletableFuture.supplyAsync(() -> {
        System.out.println("Running...");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("...finished");
        return "finished task";
    });

    CompletableFuture<String> two = one.thenApplyAsync(s -> {
        System.out.println("Apply on result: " + s);
        return "Result: " + s;
    });

    completableFuture = two;
} 

So, one in your case starts just fine, but before two can even start, you issue completableFuture.complete("Test");所以,在你的情况下, one开始就好了,但是在two甚至可以开始之前,你发出completableFuture.complete("Test"); . . So when one is done, there is nothing for it to thenApplyAsync , since that one is already completed.因此,当one完成时, thenApplyAsync没有任何内容,因为那个已经完成了。

When you add one more stage, you basically get:当您再添加一个阶段时,您基本上会得到:

....
CompletableFuture<String> two = one.thenApplyAsync(s -> {
     System.out.println("Apply on result: " + s);
     return "Result: " + s;
});

CompletableFuture<String> three = two.thenApplyAsync(s -> {
     System.out.println("Second apply with result: " + s);
     return "Result: " + s;
});

completableFuture = three;

You can probably see what happens here, without even me explaining.你可能会看到这里发生了什么,甚至不用我解释。


To that end, I can't see where the documentation would make this clear though.为此,我看不出文档在哪里可以清楚地说明这一点。 I guess we somehow need to see that in package documentation , via:我想我们需要通过以下方式在package 文档中看到这一点:

When two or more threads attempt to complete, completeExceptionally, or cancel a CompletableFuture, only one of them succeeds.当两个或更多线程尝试完成、完成异常或取消 CompletableFuture 时,只有其中一个成功。

This somehow implies that if a certain stage is not yet started, but someone else, externally complete s it;这在某种程度上意味着,如果某个阶段尚未开始,但由其他人完成,则在外部complete它; that stage will not run at all.那个阶段根本不会运行。 This makes sense, but the package documentation could be more clear, imo.这是有道理的,但 package 文档可能更清楚,imo。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM