Location>code7788 >text

How to safely release CompletableFuture? Java9 new method analysis

Popularity:402 ℃/2025-01-30 10:50:02

How to safely release CompletableFuture? Java9 new method analysis

This article is not allowed to be reproduced without permission.

In JDK9, new enhancement has been made for CompletableFuture, exceptTimeout function(Ortimeout), as well as related methods such as inheritance and safe release. In this article, we will analyze each new method in detail, and at the same time explain the importance of its safety release, and finally put forward relevant practical principles.

1. newIncompleteFuture

public <U> CompletableFuture<U> newIncompleteFuture() {
    return new CompletableFuture<U>();
}

This is a method of inheritance. The Java support method returns the value of the value, and the subclass can return its own implementation. If you don't need to inherit the CompletableFuture, this method does not add new features for this method.

2. Default actuator

public Executor defaultExecutor() {
    return ASYNC_POOL;
}

Subclass can specify the default actuator. However, when calling the async related method of the non -explicitly specified actuator, there are two possibilities for the thread where the recovery is located: the currently calling thread or the designated actuator thread specified by the subclass. If you use CompletableFuture, it is recommended to explicitly specify the actuator; if you use CFFU, you do not need to display the actuator every time.

3. Copy method

public CompletableFuture<T> copy() {
    return uniCopyStage(this);
}

This method is equivalent to calling(x -> x)The purpose is to achieve protective replication to avoid the modification of the original instance.

4. Read only form and safe release

// The return result only supports CompletionStage operation
 Public CompletionStage <t> MinimalCompleTionStage () {) {
     Return uniasminimalstage ();
 }

 Private MinimalStage <t> UniasminimalStage () {
     Object R;
   // Performance Optimization 1: If the results are already available, return the Stage directly under the current thread
     if ((R = Result)! = NULL)
         Return new minimalstage <t> (enCodeRelay (R));
   // Performance optimization 2: If there is no result, register a callback
     Minimalstage <t> d = new minimalstage <t> ();
     Unipush (new unirelay <t, t> (d, this));
     Return d;
 }

 // Actual implementation, the unique method of CompletableFuture does not support
 static final minimalstage <t> Extends CompletableFuture <t> {{{{{{{
         Minimalstage () {}
         Minimalstage (object r) {super (r);}
         @Override Public <u> CompletableFuture <u> newCompleTeFuture () {
             Return new minimalstage <u> ();}
         @Override Public T Get () {
             Throw New UnupportedOperationException ();}
         @Override Public T Get (Long Timeout, TimeUnit Unit) {
             Throw New UnupportedOperationException ();}
         @Override Public T Getnow (T ValueifabSEnt) {
             Throw New UnupportedOperationException ();}
         @Override Public T Join () {
             Throw New UnupportedOperationException ();}
         @Override Public T Resultnow () {
             Throw New UnupportedOperationException ();}
         @Override Public Throwable ExceptionNow () {{)
             Throw New UnupportedOperationException ();}
         @Override Public Boolean Complete (T Value) {
             Throw New UnupportedOperationException ();}
         @Override Public Boolean Completexceptionally (Throwable EX) {{
             Throw New UnupportedOperationException ();}
         @OOVERRIDE PUBLIC BOOLEN Cancel (Boolean Mayinterruptifrunning) {{
             Throw New UnupportedOperationException ();}
         @Override Public Void Obtrudevalue (T Value) {
             Throw New UnupportedOperationException ();}
         @Override Public Void ObtrudeException (Throwable EX) {
             Throw New UnupportedOperationException ();}
         @Override Public Boolean Isdone () {) {)
             Throw New UnupportedOperationException ();}
         @Override Public Boolean Iscancelled () {
             Throw New UnupportedOperationException ();}
         @Override Public Boolean IsCompleTExceptionally () {
             Throw New UnupportedOperationException ();}
         @Override Public State State () {) {)
             Throw New UnupportedOperationException ();}
         @Override Public int GetnumberOFDEPENTS () {
             Throw New UnupportedOperationException ();}
         @Override Public CompletableFuture <t> Completeasync
             (SUPPLIER <? Extens T> Supplier, Executor Executor) {
             Throw New UnupportedOperationException ();}
         @Override Public CompletableFuture <t> Completeasync
             (SUPPLIER <? Extens t> support) {
             Throw New UnupportedOperationException ();}
         @Override Public CompletableFuture <T> Ortimeout
             (Long Timeout, Timeunit Unit) {
             Throw New UnupportedOperationException ();}
         @Override Public CompletableFuture <t> Completeontimeout
             (T value, Long Timeout, Timeunit Unit) {
             Throw New UnupportedOperationException ();}
   // Return to the new CompletableFuture, which is equivalent to thenApply (x-> x)
         @Override Public CompletableFuture <t> TocompletableFuture () {{
             Object R;
             if ((R = Result)! = NULL)
                 Return New CompletableFuture <T> (Encoderelay (R));
             else {
                 CompletableFuture <t> d = New CompletableFuture <> ();
                 Unipush (new unirelay <t, t> (d, this));
                 Return d;
             }
         }
     }

This method returns the readstage that is only readable, which can achieve safe release. It can be analogy to one method to return ImmutableList. The advantage is that it can prevent subsequent error operations, such as other threads forced writing results (List#ADD).

There is such a safe release guarantee, especially when facing complex scenarios, you can reduce the burden of programming and use the CompletableFuture back with confidence.

We know that the CompletionStage interface defines the chain asynchronous callback -related method. CompletableFuture -related reading and writing operations (Join, Complete, Obtrudeval, etc.), are not under the definition of CompletionStage, you can use the method to turn on to the TocompleTableFuture.

Class InventoryServicedemo {
     FINAL Executor Executor = ();

     // Get inventory information
   // The method can return to CompletionStage, which is safer than CompletableFuture
     Completor <Integer> Getinventoryasync (String Productid) {{
         Return (() -> {
                     try {
                         (2);
                     } Catch (InterruptedException E) {{
                         Throw New Runtimeexception (E);
                     }
                     Return 42;
                 }, Executor)
                 . MinimalCompltingStage ();
     }
 }

I used to"In -depth understateIn a article, questioningStage#ToCompletableFuture method destroys the relevant principles of the interface design. CompletableFuture#minimalCompleTionStage is not as good as using the interface.

  1. CompletionStage#TocompletableFuture indicates that CompletableFuture can be used as the default implementation of CompletionStage to achieve rapid conversion of the two types. In many cases, the difference between the two is not much.
  2. CompletableFuture#MinimalCompltingStage underlying thought is to provide read -only function.
  3. The implementation here is a bit clever. Although the MinimalStage inherits the CompletableFuture, it actually only implements the CompletionStage interface method. MinimalStage should not be an example of the CompletableFuture. The better implementation method is to use the commission method (combination).
  4. If the subclacium is checked, the minimalStage needs to be applied with Instanceof or the new version of the JDK supported mode.
  5. The implementation of CFFU is compatible with minimalstage, and you can use it with confidence.

5. Asynchronous writing operation

public CompletableFuture<T> completeAsync(Supplier<? extends T> supplier) {
    return completeAsync(supplier, defaultExecutor());
}

public CompletableFuture<T> completeAsync(Supplier<? extends T> supplier,
                                          Executor executor) {
    if (supplier == null || executor == null)
        throw new NullPointerException();
    (new AsyncSupply<T>(this, supplier));
    return this;
}

These two methods are easy to understand, and it is suitable for subcretions of subclasses. CompletableFuture#SUPPLYASYNC factory method returns a complteableFuture cannot be changed. The subclass can define its own factory method; users can also use the asynchronous writing method here.

6. Optimization and expansion of CFFU

The open source project CFFU (Kung Fu Future) expands the CompletableFuture. The following only enumerated expansion points related to the new features of Java9:

  1. You can specify the actuator when the object is created. The follow -up operation does not need to be repeatedly specified
  2. You can use the function of the follow -up version under the java8 version
  3. Provided related security release functions, such asSafe timeout function
  4. Many internal convenience methods apply protective copying methods
  5. CFFUFUFACTORYBUILEDER supports whether the configuration of the parameter is allowed to be forced to rewrite the results

7. Practice principles

  1. The asynchronous method can return CompletionStage, which is safer than CompletableFuture. At the same time
  2. Just like it is recommended to use unsatisfactory objects, it is recommended to use CompletableFuture#MinimalCompltingStage method by default
  3. Regardless of the method of entering the parameters or returning results, the use of the interface is generally better than the physical category
  4. The ideal Future design should be read and write separately. Although CompletableFuture does not fully follow the above principles, we should pay attention to follow when using it.