2

Completable Future Improvements in Java9 - Knoldus Blogs

 3 years ago
source link: https://blog.knoldus.com/completablefuture-improvements-in-java9/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Completable Future Improvements in Java9

Reading Time: 3 minutes

In this article, I will be talking about the improvements and enhancements done in the CompletableFuture class and CompletionStage interface as part of Java9 release. There were a lot of improvements done in the class and interface and new methods were added to them, the biggest improvement was to handle timeout asynchronously which was not seen in Java8.

Completable Future improvements at glance (only the common methods)

  1. defaultExecutor method
  2. copy method
  3. completeAsync method
  4. orTimeout method
  5. completeOnTimeout method
  6. New Factory methods

Let’s talk about these methods in detail to better understand them one by one.

1. defaultExecutor() – This method essentially returns the default executor for futures which do not specify an executor.

defaultExecutor() method in action

Executor executor = new CompletableFuture<>().defaultExecutor();

CompletableFuture nameFuture = CompletableFuture.supplyAsync(() -> "Deepak", executor);

// Should be avoided, only for demonstration purpose

System.out.println(nameFuture.join());

2. copy() – returns an immutable copy of the existing CompletableFuture instance, since the copy is immutable it would not affect the original instance in any way.

copy() method in action

CompletableFuture nameFuture = CompletableFuture.supplyAsync(() -> "Deepak");

CompletableFuture nameFutureCopy = nameFuture.copy();

CompletableFuture withSurname = nameFuture.thenApply(name -> "Deepak Mehra");

// Should be avoided, only for demonstration purpose

System.out.println(withSurname.join());

// Change in original instance should affect it's copy instance.

System.out.println(nameFutureCopy.join());

3. completeAsync() – Completes this CompletableFuture with the result of the given Supplier function invoked from an asynchronous task using the default executor.

completeAsync() method in action –

CompletableFuture completableFuture = new CompletableFuture();

CompletableFuture nameFuture = completableFuture.completeAsync(() -> "Deepak");

// Should be avoided, only for demonstration purpose

System.out.println(nameFuture.join());

The 4th and 5th methods were essentially introduced to support delay and timeouts and still keep everything non-blocking.

4. orTimeout – Prior to orTimeout() what we had, was the get() method where we can define the Time Units and if the future call is not completed in that particular time, it will raise the timeout exception but this method will block the thread and as a result it will not be non-blocking anymore. In order to deal with this, Java9 introduced orTimeout() which will provide us the timeout functionality and keep the calls non-blocking at the same time i.e the thread will not be blocked for that point of time and you can still have the timeout feature for your future calls.

Let’s understand this with the help of an example here. Suppose, you have a service getUsers which will get you a list of users. Now, you want to throw a timeout exception if the userlist is not returned in 1 seconds say, if you do this with the help of get() method you will be blocking the thread. However, with the use of orTimeout() you can throw TimeoutException and still keep everything non-blocking.

orTimeout in action

public class OrTimeoutDemo {

public static void main(String[] args) {

CompletableFuture orTimeout = CompletableFuture.supplyAsync(() -> {

try {

return getUsers();

} catch (Exception ex) {

System.out.println(ex.getMessage());

return null;

}

})

.orTimeout(1, TimeUnit.SECONDS);

// Should be avoided, only for demonstration purpose

System.out.println(orTimeout.join());

}

private static List getUsers() throws Exception {

// If this value will be more than 1000 i.e more than 1 second, timeout will be raised

Thread.sleep(100);

List users = Arrays.asList("Deepak", "Ayush", "Nitesh", "Santosh", "Simran");

return users;

}

}

5. completeOnTimeout – This method is essentially similar to orTimeout(). However, with this method you can also provide a default or static value if the service is taking too long to respond or there is a TimeoutException. This works more like a method which is capable of returning a fallback value when something goes wrong.

completeOnTimeout() in action –

public class CompleteOnTimeoutDemo {

public static void main(String[] args) {

CompletableFuture orTimeout = CompletableFuture.supplyAsync(() -> {

try {

return getUsers();

} catch (Exception ex) {

System.out.println(ex.getMessage());

return null;

}

})

.completeOnTimeout(getUsersFallback(), 1, TimeUnit.SECONDS);

System.out.println(orTimeout.join());

}

private static List getUsers() throws Exception {

// In this case fallback method will be invoked, if this value is lesser than 1000, i.e 1 second, it will invoke the service only.

Thread.sleep(2000);

List users = Arrays.asList("Deepak", "Ayush", "Nitesh", "Santosh", "Simran");

return users;

}

private static List getUsersFallback() {

return Arrays.asList("Fallback List");

}

}

Apart from these methods, some factory methods were also introduced as part of the improvements to CompletableFuture.

New Static Factory Methods
completedFuture() – Returns a new CompletableFuture that is already completed with the given value.
completedStage() – Returns a new CompletionStage that is already completed with the given value and supports only those methods in interface CompletionStage.
failedStage() – Returns a new CompletionStage that is already completed exceptionally with the given exception and supports only those methods in interface CompletionStage

completedFuture() signature – public static CompletableFuture completedFuture(U value)

completedStage() signature – public static CompletionStage completedStage(U value)

failedStage() signature – public static CompletionStage failedStage(Throwable ex)

Static Factory Methods in Action –

CompletableFuture name = CompletableFuture.completedFuture("Deepak");

CompletionStage name With CompletionStage = CompletableFuture.completedStage("Deepak");

CompletableFuture failedFuture = failedFuture(new TimeoutException());

System.out.println(failedFuture.join());

That’s pretty much it from the article, full code can be found on the GitHub repository, feel free to fork it and start practicing the examples. If you have any feedback or queries, please do let me know in the comments. Also, if you liked the article, please give me a thumbs up and I will keep writing blogs like this for you in the future as well. Keep reading and Keep coding 🙂


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK