Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”

This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.

1, CompletableFuture

An asynchronous callback

An asynchronous callback is a function that is specified when an asynchronous task is initiated. The function is called automatically when the task is completed.

CompletableFuture

A Future represents the result of an asynchronous task that may not have completed, to which a Callback can be added to act upon the success or failure of the task.

When you get asynchronous execution results using a Future, you either call the blocking method get() or poll to see if isDone() is true, neither of which is very good because the main thread is forced to wait, too.

The CompletableFuture, the implementation class of the Future, has been introduced since Java 8. It improves on the Future by passing in a callback object whose callback method is automatically called when an asynchronous task completes or an exception occurs. A completableFuture object represents a task

The advantages of CompletableFuture are:

  • Methods that are automatically called back to an object when an asynchronous task ends.
  • When an asynchronous task fails, it automatically calls back an object’s method.
  • The main thread no longer cares about the execution of asynchronous tasks after the callback is set.

2. Implement asynchronous callback

2.1. Asynchronous Tasks

Create an asynchronous task with no return value:

public class Demo01 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //runAsync performs an asynchronous task with no return value
        CompletableFuture<Void> future = CompletableFuture.runAsync(()->{
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+" ->runAsync->void");
        });
        // Get the result of the asynchronous taskfuture.get(); }}Copy the code

RunAsync creates an asynchronous task with no return value. There is an overloaded version of this method that specifies the Executor implementation that executes the asynchronous task. If this is not specified, ForkJoinPool.commonPool() is used by default.

Create an asynchronous task with a return value:

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(()->{
    System.out.println(Thread.currentThread().getName()+" ->supplyAsync->Integer");
    return 1024;
});
Copy the code

SupplyAsync creates an asynchronous task that returns a value. There is an overloaded version of this method that specifies the Executor implementation that performs the asynchronous task. If not, ForkJoinPool.commonPool() is used by default.

2.2. Asynchronous callback

An asynchronous callback

Create a callback method for an asynchronous task:

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(()->{
    System.out.println(Thread.currentThread().getName()+" ->supplyAsync->Integer");
    // If the task is successfully executed, 1024 is returned
    return 1024;
});

// The callback function
CompletableFuture<Integer> whenComplete = future.whenComplete((t,u)->{
    // Prints two arguments
    System.out.println("t->"+t);
    System.out.println("u->"+u);
}).exceptionally((e)->{
    System.out.println(e.getMessage());
    // If the task execution is abnormal, return 500
    return 500;
});
System.out.println(whenComplete.get());// Get the result of the asynchronous task
Copy the code

WhenComplete () : Callback method that executes when a task is completed, handles the result when the CompletableFuture completes the calculation, or handles the exception when the CompletableFuture generates an exception.

WhenComplete () the source code:

    public CompletableFuture<T> whenComplete(
        BiConsumer<? super T, ? super Throwable> action) {
        return uniWhenCompleteStage(null, action);
    }

    public CompletableFuture<T> whenCompleteAsync(
        BiConsumer<? super T, ? super Throwable> action) {
        return uniWhenCompleteStage(asyncPool, action);
    }

    public CompletableFuture<T> whenCompleteAsync(
        BiConsumer<? super T, ? super Throwable> action, Executor executor) {
        return uniWhenCompleteStage(screenExecutor(executor), action);
    }
Copy the code

WhenComplete and whenCompleteAsync

WhenComplete: The thread that executes the current task executes the task that continues to execute whenComplete.

WhenCompleteAsync: The execution continues the task whenCompleteAsync to the thread pool for execution.

You can see that the Action type is BiConsumer<? super T,? Super Throwable> It can handle normal calculation results, or exception cases.

BiConsumer can accept two arguments:

The exceptionally method specifies the callback method that executes when a task executes an exception. It passes the exception as an argument to the callback method. The result returned by the method is the exceptionally result if the task executes normally.

View the output of the callback function and its parameters when the above task is executed normally:

View the output of two parameters when a task is executed abnormally:

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(()->{
    System.out.println(Thread.currentThread().getName()+" ->supplyAsync->Integer");
    int i = 10 / 0;
    return 1024;
});
Copy the code

WhenComplete passes the callback method the result of asynchronous task execution or the exception thrown during execution,

If the task is executed properly, the get method displays the normal execution result, and the exception output is NULL

If the task execution is abnormal: The GET method outputs abnormal execution results and displays abnormal information