[concurrency-interest] CompletableStage.whenComplete(): Completes the stage after calling the BiConsumer

Nathan and Ila Reynolds nathanila at gmail.com
Thu Nov 7 18:42:09 EST 2019


UnableToParseQuestionException  ;)

Let's use the following simplified code.

CompletableFuture<String> future;

public void startSomething()
{
    CompletableFuture<String> async;

    async  = CompletableFuture.supplyAsync(() -> produce());
    future = async.whenComplete((value, throwable) -> doSomething1());
}

public String produce()
{
    Thread.sleep(1000);  // A long operation
    return("Hello");
}

public void doSomething1()
{
    doSomething2();
}

public void doSomething2()
{
    doSomething3();
}

public void doSomething3()
{
    doSomething4();
}

public void doSomething4()
{
    if (future.getNow(null) == null)
       throw new IllegalStateException("I wanted \"Hello\"");
}

Here are my questions now more refined...

Why does "future" not complete until after the action in whenComplete() 
returns?  How do I exploit this behavior?

How do I get the value from "future" in doSomething4()?


I could pass the "Hello" value through the doSomething#(), but that will 
require creating duplicate methods because other code uses the 
doSomething#() as they are.  I could pass null or value depending on the 
use case but that makes the methods complicated.

I cannot access "async" since that is long gone from the stack of 
probably another thread.  I could save "async" in a separate field but 
that wastes heap space.

I could change startSomething() to the following.  If I understand 
correctly, "unused" could be GCed and whenComplete() will never execute.

public void startSomething()
{
    CompletableFuture<String> unused;

    future = CompletableFuture.supplyAsync(() -> produce());
    unused = future.whenComplete((value, throwable) -> doSomething1());
}

-Nathan

On 11/7/2019 2:41 PM, Martin Buchholz wrote:
> https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/util/concurrent/CompletionStage.html#whenComplete(java.util.function.BiConsumer)
>
> On Thu, Nov 7, 2019 at 10:49 AM Nathan and Ila Reynolds via 
> Concurrency-interest <concurrency-interest at cs.oswego.edu 
> <mailto:concurrency-interest at cs.oswego.edu>> wrote:
>
>     For CompletableStage.whenComplete(), the Javadoc says "The returned
>     stage is completed when the action returns."  What is the
>     reasoning for
>     completing the future after action returns? 
>
>
> The result of the returned stage depends on whether the action failed 
> or not.
>
>     How do I run action after
>     the future completes?
>
>
> Why can't you just attach a completion action to either the stage 
> returned by whenComplete or its source?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20191107/1fddf080/attachment.html>


More information about the Concurrency-interest mailing list