简体   繁体   中英

Completable future - complete method

I have a code:

CompletableFuture<Integer> c1 = new CompletableFuture<Integer>()
        .thenApply((data) -> data * 2);
c1.thenAccept(System.out::println);

c1.complete(20);


CompletableFuture<Integer> c2 = new CompletableFuture<>();

c2.thenApply(data -> data * 2)
        .thenAccept(System.out::println);
c2.complete(20);

Output:

20 40

Question:

  1. Why there is a difference in output between c1 and c2?
  2. Why there is a need to repeat future type in c1 by calling:

new CompletableFuture< Integer >()

The first thing to note is that the methods of CompletableFuture (eg thenApply , thenAccept , etc.) return a new CompletableFuture instance. This forms a sort of "chain" where each new stage is dependent on the stage it was created from—its parent stage. When a stage completes, normally or exceptionally, the result is pushed to all its dependent, non-completed * stages (the same stage can have multiple dependent stages).


* As you'll see below you can complete a stage even if its parent hasn't completed yet. If and when the parent stage completes the completed dependent stage(s) will not be invoked as it's already completed. The consequences of this are covered briefly in an answer by Holger to another question.


Question 1

In your first example you have the following:

CompletableFuture<Integer> c1 = new CompletableFuture<Integer>()
        .thenApply((data) -> data * 2);
c1.thenAccept(System.out::println);
c1.complete(20);

Here c1 is the stage resulting from thenApply , not new CompletableFuture<Integer>() . When you call c1.complete(20) you are completing the thenApply stage (normally) with the given value ( 20 ). The call to complete is equivalent to the Function transforming the previous stage's result and returning 20 . Now that thenApply is completed it pushes the value to thenAccept which results in 20 being printed to the console.

In your second example you have the following:

CompletableFuture<Integer> c2 = new CompletableFuture<>();
c2.thenApply(data -> data * 2)
        .thenAccept(System.out::println);
c2.complete(20);

Here c2 is the stage resulting from new CompletableFuture<>() , which is the parent of the thenApply stage. So now when you call c2.complete(20) you are completing the root stage which pushes the value to thenApply . The Function then transforms the value by multiplying it by 2 and pushing that result to thenAccept . This results in 40 being printed out to the console.


Question 2

The reason you must repeat <Integer> in your first example is because the compiler cannot infer the type of the first stage without it. The signature of thenApply is:

<U> CompletableFuture<U> thenApply(Function<? super T, ? extends U>)

The T is determined by the type of this CompletableFuture (the one the method is invoked on). The U is determined by the Function and, to an extent, the left hand side of a variable assignment where applicable. This means when you use the diamond operator ( <> ) you are effectively using the following:

CompletableFuture<Integer> c = new CompletableFuture<Object>()
        .thenApply(data -> data * 2);

// same as...
CompletableFuture<Integer> c = new CompletableFuture<>()
        .thenApply(data -> data * 2);

Since all the compiler knows about the type of data is that it's an Object the multiplication is invalid; an Object cannot be multiplied by 2 . Note that the above would be valid if you simply changed the Function from data -> data * 2 to data -> 2 (but obviously those two functions aren't equivalent). This is because the left hand side of the assignment is related to the result of thenApply , not new CompletableFuture<>() .

When you explicitly specify <Integer> the compiler then knows that the input type ( T ) of the thenApply stage is Integer , which means it knows data is an Integer ; an Integer can be multiplied by 2 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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