Basic Usage and Summary of CompletableFuture

CompletableFuture Asynchronous Ordering

CompletableFuture provides four static methods to create an asynchronous operation

//A Runnable is passed in, which is characterized by no return value
public static CompletableFuture<Void> runAsync(Runnable runnable)
//A Runnable is passed in, which is characterized by the ability to specify execution in that thread pool, i.e. Executor, without requiring a return value
public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor)
//An asynchronous task was passed in, but with a return value
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
//Incoming an asynchronous task to execute, but with a return value, you can specify which thread pool to execute, Executor
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor)

1, Create Asynchronous Method

(1) Using runAsync test

public class CompletableFutureTest {
    //Creating a thread pool is not recommended. This is mainly about CompletableFuture, not detailed in the Thread Pool section.
    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) {
        System.out.println("main Method begins.");
        CompletableFuture.runAsync(() -> {
            System.out.println("Current Thread:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("Run result:" + i);
        },executor);//Use our own thread pool
        System.out.println("main Method end.");
    }
}

Run result:
The main method begins.
The main method ends.
Current Thread: 11
Run result: 5
(2) Using the supplyAsync test

public class CompletableFutureTest {
    //Creating a thread pool is not recommended. This is mainly about CompletableFuture, not detailed in the Thread Pool section.
    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main Method begins.");
        //A CompletableFuture is returned whenever an asynchronous task is started
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("Current Thread:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("Run result:" + i);
            return i;
        }, executor);
        //Get the return value of an asynchronous task
        Integer integer = future.get();
        System.out.println("main Method end." + integer);
    }
}

Run result:
The main method begins.
Current Thread: 11
Run result: 5
The main method ends.5
(3) Summary
1, runXxxx is not returned, supplyXxx is returnable
2. Custom thread pools can be passed in, otherwise default thread pools will be used;

2, CompletableFuture Complete callbacks and anomaly perception

Callback method on completion of calculation

public completableFuture<T> whenComplete(BiConsumer <? super T,? super Throwable> action);
public completableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable>action);
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable>action,Executor executor);
public completableFuture<T> exceptiona1ly(Function<Throwable,? extends T fn);

details
1. When Complete handles both normal and abnormal calculations, and exceptionally handles exceptions.
2. The difference between whenComplete and whenCompleteAsync:
(1), whenComplete: is the thread executing the current task to continue execution
(2) When Complete's task.whenCompleteAsync: is the execution handle
(3) When the task completeAsync continues to be committed to the thread pool for execution.

public class CompletableFutureTest {
    //Creating a thread pool is not recommended. This is mainly about CompletableFuture, not detailed in the Thread Pool section.
    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main Method begins.");
        //A CompletableFuture is returned whenever an asynchronous task is started
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("Current Thread:" + Thread.currentThread().getId());
            int i = 10 / 0;
            System.out.println("Run result:" + i);
            return i;
        }, executor).whenComplete((res,exception) -> {
            //Exception information is available, but return data cannot be modified
            System.out.println("The asynchronous task completed successfully.The result is:" + res + "The exception is:" + exception);
        }).exceptionally(throwable -> {
            //Can sense exceptions and return defaults
            return 10;
        });
        //Get the return value of an asynchronous task
        Integer integer = future.get();
        System.out.println("main Method end." + integer);
    }
}

Run result:
The main method begins.
Current Thread: 11
The asynchronous task completed successfully.The result is: null exception is: java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
The main method ends.10
Be careful
Exceptionally will enter the exceptionally () method without an exception returning normally.

3, handle method (final processing)

public class CompletableFutureTest {
    //Creating a thread pool is not recommended. This is mainly about CompletableFuture, not detailed in the Thread Pool section.
    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main Method begins.");
        
        //Processing after method execution is complete
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("Current Thread:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("Run result:" + i);
            return i;
        }, executor).handle((res,exec) -> {
            if (res != null){
                return res * 2;
            }
            if (exec != null){
                return 0;
            }
            return 0;
        });
        //Get the return value of an asynchronous task
        Integer integer = future.get();
        System.out.println("main Method end." + integer);
    }
}

Run result:
The main method begins.
Current Thread: 11
Run result: 5
The main method ends.20

Note: As with complete, the result can be processed last (exception can be handled) and the return value can be changed.

4, Thread Serialization Method

public <Us CompletableFuture<Us thenApply(Function<? super T,? extends Us fn)
public <UsCompletableFuturecUz thenApplyAsyne(Function<? super T,? extends us fn)
public <U> completableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn,Executor executor)

public completionstage<void> thenAccept(Consumer<? super T> action);
public completionstage<void> thenAcceptAsync(Consumer<? super T> action);
public completionStage<Void> thenAcceptAsync(Consumer<? super T> action,Executorexecutor);

public completionstage<Void> thenRun(Runnable action) ;
public completionstage<void> thenRunAsync(Runnable action);
public completionStage<Void> thenRunAsync(Runnable action,Executor executor );

(1), thenApply method: When one thread depends on another thread, get the result returned by the previous task and return the return value of the current task.

		//thenApplyAsync: Accepts the result of the previous step with a return value
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("Current Thread:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("Run result:" + i);
            return i;
        }, executor).thenApplyAsync(res -> {
            return "Hello" + res;
        }, executor);
        String s = future.get();
        //Get the return value of an asynchronous task
        System.out.println("main Method end." + s);

(2), thenAccept method: consumer processing results.Receives the processing results of the task, consumes the processing, and returns no results.

		//thenAcceptAsync: Accepts the previous step but has no return value
		CompletableFuture.supplyAsync(() -> {
            System.out.println("Current Thread:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("Run result:" + i);
            return i;
        }, executor).thenAcceptAsync(res -> {
            System.out.println("Task 2 started." + res);
        },executor);
        //Get the return value of an asynchronous task
        System.out.println("main Method end." );

(3), thenRun method: Start executing the thenRun as long as the above task is completed, only after the task is processed, subsequent operations to execute the thenRun are performed asynchronously by default with Async.Same as before.All of these tasks were successfully completed.

 		//thenRun: Cannot get the result of the previous step, no return value
        CompletableFuture.supplyAsync(() -> {
            System.out.println("Current Thread:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("Run result:" + i);
            return i;
        }, executor).thenRunAsync(() -> {
            System.out.println("Task 2 started.");
        },executor);
        //Get the return value of an asynchronous task
        System.out.println("main Method end." );

5, two task combinations - all done

public <U,V>CompletableFuture<V> thencombine(completionstage<? extends U> other ,BiFunction<? super T,? super u,? extends v> fn);
public <U,V> CompletableFuture<V> thencombineAsync(completionstage<? extends U> other ,BiFunction<? superT,? super U,? extends v> fn);
public <U,V> CompletableFuture<V> thenCombineAsync(Completionstage<? extends U> other ,BiFunction<? super T,? super u,? extends v> fn,Executor executor);

public UCompletableFuture<Void> thenAcceptBoth(Completionstage<? extends U> other ,Biconsumer<? super T, ? super U>action);
public <Us Completab1eFuture<void>thenAcceptBothAsync(CompletionStage<? extends U> other ,BiConsumer<? super T,?super U>action);
public <UsCompletab1eFuture<Void> thenAcceptBothAsync(completionstage<? extends U> other ,Biconsumer<? super T, ? super U>action,Executor executor);
	
public completablefuture<Void> runAfterBoth(Completionstage<?> other,Runnable action);
public CompletableFuture<Void> runAfterBothAsync(Completionstage<?> other,Runnable action);
public completableFuture<Void> runAfterBothAsync(Completionstage<?> other,Runnable action,Executor executor);

(1), thenCombine: Combine two future, get the return of two futures, and return the return value of the current task

		CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("Task 1 Thread:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("Task 1 ends:");
            return i;
        }, executor);
        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("Task 2 Threads:" + Thread.currentThread().getId());
            System.out.println("Task 2 ends:");
            return "hello";
        }, executor);
        CompletableFuture<String> future = future01.thenCombineAsync(future02, (f1, f2) -> {
            return f1 + ":::" + f2 + "->>world";
        }, executor);

        //Get the return value of an asynchronous task
        System.out.println("main Method end." + future.get());
        /**
         * Run Results
         * main Method begins.
         * Task 1 Thread:11
         * Task 1 ends:
         * Task 2 Threads:12
         * Task 2 ends:
         * main Method end.5::: hello-> world
         */

(2), thenAcceptBoth: Combine two future, get the return results of two future tasks, and then process the task with no return value.

		CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("Task 1 Thread:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("Task 1 ends:");
            return i;
        }, executor);
        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("Task 2 Threads:" + Thread.currentThread().getId());
            System.out.println("Task 2 ends:");
            return "hello";
        }, executor);
        future01.thenAcceptBothAsync(future02,(f1,f2) -> {
            System.out.println("Task 3 Starts---->Previous results:" + f1 + "===>" + f2);
        },executor);

        //Get the return value of an asynchronous task
        System.out.println("main Method end.");
        /**
         * Run Results
         * main Method begins.
         * Task 1 Thread:11
         * Task 1 ends:
         * Task 2 Threads:12
         * Task 2 ends:
         * main Method end.
         * Task 3 Starts ---- Result before: 5===>hello
         */

(3), runAfterBoth: Combines two future, does not need to get the result of the future, only two futures process the task after it has finished processing it.

CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("Task 1 Thread:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("Task 1 ends:");
            return i;
        }, executor);
        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("Task 2 Threads:" + Thread.currentThread().getId());
            System.out.println("Task 2 ends:");
            return "hello";
        }, executor);
        future01.runAfterBothAsync(future02,() -> {
            System.out.println("Task 3 Starts");
        },executor);
        //Get the return value of an asynchronous task
        System.out.println("main Method end.");
		/**
         * Run Results
         * main Method begins.
         * Task 1 Thread:11
         * Task 1 ends:
         * main Method end.
         * Task 2 Threads:12
         * Task 2 ends:
         * Task 3 Starts
         */

6. Two Tasks - One Complete

public <U>completab1eFuture<U applyToEither(completionstage<? extends T> other,Function<? super T, U> fn);
public <U> completableFuturecU> applyToEither Async(completionstage<? extends T> other ,Function<? super T,U> fn);
public <UCompletableFuture<Ux applyToEither Asyne(completionstage<? extends T> other,Function<? super T,U>fn,Executor executor ) ;


public completableFuture<Void> acceptEither(completionstage<? extends T> other,Consumer<? super T> action);
public completableFuture<Void> acceptEitherAsync(completionstage<? extends T other,Consumer<? super T> action);
public comp1etab1eFuture<Void> acceptEitherAsync(completionstage<? extends T> other,Consumer<? super T> action,Executor executor);


public completableFuture<Void> runAfterEither (Completionstage<?> other ,Runnable action);
public CompletableFuture<Void> runAfterEitherAsync(Completionstage<?> other ,Runnable action);
public completableFuture<Void runAfterEither Async(Completionstage<?> other ,Runnable action,Executor executor);

Execute the task when either of the two tasks is completed.
(1), applyToEither: Two tasks have one execution completed, get its return value, process the task, and have a new return value.

		//applyToEitherAsync perceives the result, with a return value
		CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("Task 1 Thread:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("Task 1 ends:");
            return i;
        }, executor);
        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("Task 2 Threads:" + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
                System.out.println("Task 2 ends:");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello";
        }, executor);
        CompletableFuture<String> future = future01.applyToEitherAsync(future02, res -> {
            System.out.println("Task 3 starts.Previous results:" + res);
            return res.toString() + "===>Love and love you";
        }, executor);
        //Get the return value of an asynchronous task
        System.out.println("main Method end." + future.get() );
        /**
         * Run Results
         * main Method begins.
         * Task 1 Thread:11
         * Task 1 ends:
         * Task 3 starts.Previous results: 5
         * main Method end.5===>Love you very much
         * Task 2 Threads:12
         */

(2), acceptEither: Two tasks have one execution completed, get its return value, process the task, no new return value.

		//acceptEitherAsync: perceived result, no return value
		CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("Task 1 Thread:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("Task 1 ends:");
            return i;
        }, executor);
        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("Task 2 Threads:" + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
                System.out.println("Task 2 ends:");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello";
        }, executor);
        future01.acceptEitherAsync(future02,res -> {
            System.out.println("Task 3 starts.Previous results:" + res);
        },executor);
        //Get the return value of an asynchronous task
        System.out.println("main Method end." );
        /**
         * Run Results
         * main Method begins.
         * main Method end.
         * Task 2 Threads:12
         * Task 1 Thread:11
         * Task 1 ends:
         * Task 3 starts.Previous results: 5
         */

(3), runAfterEither: Two tasks have one execution completed, do not need to get the result of the future, process the task, and do not return a value.

		//Two tasks, as long as one is completed, we will perform task 3
		//runAfterEitherAsync: No result is aware, no return value
		CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("Task 1 Thread:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("Task 1 ends:");
            return i;
        }, executor);
        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("Task 2 Threads:" + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
                System.out.println("Task 2 ends:");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello";
        }, executor);
        future01.runAfterEitherAsync(future02,() -> {
            System.out.println("Task 3 starts.Previous results");
        },executor);
        //Get the return value of an asynchronous task
        System.out.println("main Method end." );
        /**
         * Run Results
         * main Method begins.
         * Task 1 Thread:11
         * Task 1 ends:
         * Task 2 Threads:12
         * main Method end.
         * Task 3 starts.Previous results
         * Task 2 ends:
         */

7, Multitask Combination

public static completableFuture<Void>a110f(completableFuture<?>...cfs);
public static completableFuture<object> anyof(CompletableFuture<?>... cfs);

(1), allOf: Wait for all tasks to be completed anyOf: as long as one task is completed

		CompletableFuture<String> future01 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
                System.out.println("Use the toilet");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Squat Toilet";
        }, executor);

        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("Brush jitter");
            return "Watch sister dance";
        }, executor);

        CompletableFuture<String> future03 = CompletableFuture.supplyAsync(() -> {
            System.out.println("smoking");
            return "Sucking Hibiscus";
        }, executor);

        CompletableFuture<Void> allOf = CompletableFuture.allOf(future01, future02, future03);
        allOf.get();//Wait for all results to complete


        //Get the return value of an asynchronous task
        System.out.println("main Method end." + future01.get() + future02.get() + future03.get());
        /**
         * Run Results
         * main Method begins.
         * Brush jitter
         * smoking
         * Use the toilet
         * main Method end.Squat Toilet to Watch Miss Sister Dance and Suck Hibiscus
         */

(2), anyOf: As long as one task is completed

		CompletableFuture<String> future01 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
                System.out.println("Use the toilet");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Squat Toilet";
        }, executor);

        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("Brush jitter");
            return "Watch sister dance";
        }, executor);

        CompletableFuture<String> future03 = CompletableFuture.supplyAsync(() -> {
            System.out.println("smoking");
            return "Sucking Hibiscus";
        }, executor);

        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(future01, future02, future03);

        //Get the return value of an asynchronous task
        System.out.println("main Method end." + anyOf.get());
        /**
         * Run Results
         * main Method begins.
         * Brush jitter
         * main Method end.Watch sister dance
         * smoking
         */

Tags: Java Spring Multithreading JUC

Posted on Fri, 03 Sep 2021 12:50:08 -0400 by brattt