How to use CompletableFuture asynchronous orchestration?

Overview:

When doing the order submission function, we need to deal with a lot of things, such as: modifying inventory, calculating discount promotion information, adding and subtracting member points, online payment, amount calculation, generating product orders, generating financial information, deleting shopping carts, etc. If all these functions are serialized, it will take a long time, especially when a large amount of data is concurrent, it may cause various abnormalities such as server crashes.

The emergence of CompletableFuture asynchronous orchestration completely solves the above situation, and these functions can basically be processed in parallel. So what is CompletableFuture asynchronous orchestration?

  • CompletableFuture asynchronous orchestration is an asynchronous programming tool introduced in Java 8, which provides a convenient way to handle asynchronous tasks.

  • Asynchronous orchestration refers to the combination and execution of multiple asynchronous tasks according to a certain order or dependency relationship to implement more complex business logic.

  • getThe CompletableFuture class implements the Future interface, so you can still get results by method blocking or
    polling as before , but this method is not recommended.

  • Both CompletableFuture and FutureTask belong to the implementation class of the Future interface, and both can obtain the execution result of the thread.

As shown in the picture:
insert image description here

When orchestrating asynchronous operations, CompletableFuture provides methods, such as thenApply, thenAccept, thenRun, etc., which allow you to perform some operations after the asynchronous operation completes. These methods are highlighted below.

1. Create an asynchronous object

1 Basic method

CompletableFuture provides four static methods to create an asynchronous operation.

static CompletableFuture<Void> runAsync(Runnable runnable)
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executorexecutor)

1. runXxxx does not return a result, and supplyXxx can get a return result.
2. You can pass in a custom thread pool, otherwise use the default thread pool;

2 example:

  public static void runAsync() {
    
    
        System.out.println("runAsync....start....");
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("计算结果:" + i);
        }, executorService);
        System.out.println("runAsync....end....");
    }

2. The callback method when the calculation is completed

1 Basic method

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> exceptionally(Function<Throwable,? extends T> fn);
  • whenComplete can handle normal and abnormal calculation results, and exceptionally handles abnormal conditions.
  • The difference between whenComplete and whenCompleteAsync:

whenComplete: The thread that executes the current task executes the task that continues to execute whenComplete.
whenCompleteAsync: is to execute the task of whenCompleteAsync to continue to submit to the thread pool for execution

The method does not end with Async, which means that Action uses the same thread to execute, and Async may use other threads
to execute (if it uses the same thread pool, it may also be selected for execution by the same thread)

2 examples

public static void suplyAsync() {
    
    
        try {
    
    
            System.out.println("suplyAsync....start....");
            CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
                System.out.println("当前线程:" + Thread.currentThread().getId());
                int i = 10 / 0;
                System.out.println("计算结果:" + i);
                return i;
            }, executorService).whenComplete((res, err) -> {
                System.out.println("异步任务完成了..结果.." + res);
                System.out.println("异步任务完成了..异常.." + err);
            }).exceptionally(throwable -> {
                System.out.println("发生了异常.返回默认值....");
                return 10;
            });
            System.out.println("最终结果:" + future.get());
            System.out.println("suplyAsync....end....");
        } catch (Exception e) {
    
    
            throw new RuntimeException(e);
        }
    }

Three, handle method

1 Basic method

public <U> Completionstage<U> handle(BiFunction<? super T, Throwable,? extends U> fn);
public <U> Completionstage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U>fn);
public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U>
fn,Executor executor);

Like complete, it can do final processing on the result (can handle exceptions), and can change the return value.

2 examples

//完成后的处理
public static void suplyAsyncHandler() {
    
    
    try {
    
    
        System.out.println("suplyAsyncHandler....start....");
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("计算结果:" + i);
            return i;
        }, executorService).handle((res, err) -> {
            if(res != null){
                System.out.println("res:" + res);
                return res * 2;
            }
            if (err != null){
                System.out.println("err:" + err);
                return 0;
            }
            return res;
        });
        System.out.println("最终结果====" + future.get());
        System.out.println("suplyAsyncHandler....end....");
    } catch (Exception e) {
    
    
        throw new RuntimeException(e);
    }
}

Fourth, thread serialization method

1 Basic method

public <U> CompletableFuture<u> thenApply(Function<? super T,? extends U> fn)
public <U> CompletableFuture<u> thenApplyAsync(Function<? super T,? extends U> 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);
  • thenApply method: when a thread depends on another thread, get the result returned by the previous task and return the
    return value of the current task.
  • thenAccept method: Consume processing results. Receive the processing result of the task, and consume the processing, and return no result.
  • thenRun method: As long as the above task is executed, thenRun will be executed, and only after the task is processed, the
    follow-up operation of thenRun will be executed
  • With Async it is executed asynchronously by default. Same as before.

All of the preceding tasks must be successfully completed.

Function<? super T,? extends U>
T:上一个任务返回结果的类型
U:当前任务的返回值类型

2 examples

//---多个任务串行执行-----------------------------------------------------
    //ThenApplyAsync 可以获取上次的结果,有返回值
    public static void suplyAsyncThenApplyAsync() {
    
    
        try {
    
    
            System.out.println("suplyAsyncThenRun....start....");
            CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
                System.out.println("当前线程:" + Thread.currentThread().getId());
                int i = 10 / 2;
                System.out.println("计算结果:" + i);
                return i;
            }, executorService).thenApplyAsync((res) -> {
                System.out.println("任务1的结果是...." + res);
                System.out.println("启动任务2..........");
                return res;
            }, executorService);
            System.out.println("最终结果是:" + future);
            System.out.println("suplyAsyncThenRun....end....");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    //thenAcceptAsync 可以获取上次的结果,没返回值
    public static void suplyAsyncThenAcceptAsync() {
        try {
            System.out.println("suplyAsyncThenRun....start....");
            CompletableFuture.supplyAsync(() -> {
                System.out.println("当前线程:" + Thread.currentThread().getId());
                int i = 10 / 2;
                System.out.println("计算结果:" + i);
                return i;
            }, executorService).thenAcceptAsync((res) -> {
                System.out.println("任务1的结果是...." + res);
                System.out.println("启动任务2..........");
            }, executorService);
            System.out.println("suplyAsyncThenRun....end....");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    //thenRunAsync 不能获取上次任务的结果,没返回值
    public static void suplyAsyncThenRun() {
        try {
            System.out.println("suplyAsyncThenRun....start....");
            CompletableFuture.supplyAsync(() -> {
                System.out.println("当前线程:" + Thread.currentThread().getId());
                int i = 10 / 2;
                System.out.println("计算结果:" + i);
                return i;
            }, executorService).thenRunAsync(() -> {
    
    
                System.out.println("启动任务2..........");
            }, executorService);
            System.out.println("suplyAsyncThenRun....end....");
        } catch (Exception e) {
    
    
            throw new RuntimeException(e);
        }
    }

5. Combination of two tasks - both must be completed

1 Basic introduction

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> otherBiFunction<? super T,? 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 <U> CompletableFuture<Void> thenAcceptBoth(Completionstage<? extends U> other .BiConsumer<? super T,? super U> action);
public <U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other .BiConsumer<? super T, ? super U> action) ;
public <U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other ,BiConsumer<? super t. ? super Us action. Executor executor):

public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other.Runnable action);
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other .Runnable action):
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> otherRunnable action,
Executor executor  ;

Both tasks must be completed to trigger this task.

  • thenCombine: Combine two futures, get the return results of the two futures, and return the return value of the current task
  • thenAcceptBoth: combine two futures, get the return results of the two future tasks, and then process the tasks without
    return value.
  • runAfterBoth: combine two futures, do not need to obtain the results of the future, only need to process the task after the two futures have finished
    processing the task.

2 examples

//---任务组合-----------------------------------------------------
public static void thenCombineAsync() throws ExecutionException, InterruptedException {
    
    
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("计算结果1:" + i);
            return i;
        }, executorService);
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程2:" + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("计算结果2:" + i);
            return i;
        }, executorService);

        CompletableFuture<Integer> future3 = future1.thenCombineAsync(future2, (res1, res2) -> {
    
    
            System.out.println("线程1结果....." + res1);
            System.out.println("线程2结果....." + res2);
            System.out.println("线程3开始.....");
            return res1 + res2;
        }, executorService);

        System.out.println("线程3的结果是...." + future3.get());

    }

    public static void thenAcceptBothAsync() {
    
    
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("计算结果1:" + i);
            return i;
        }, executorService);
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程2:" + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("计算结果2:" + i);
            return i;
        }, executorService);

        future1.thenAcceptBothAsync(future2, (res1, res2)-> {
    
    
            System.out.println("线程1结果....." + res1);
            System.out.println("线程2结果....." + res2);
            System.out.println("线程3开始.....");
        }, executorService);

    }

    public static void runAfterBothAsync() {
    
    
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("计算结果1:" + i);
            return i;
        }, executorService);
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程2:" + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("计算结果2:" + i);
            return i;
        }, executorService);

        future1.runAfterBothAsync(future2, ()-> {
    
    
            System.out.println("线程3开始.....");
        }, executorService);

    }

6. Combination of two tasks - complete with one

1 Function introduction

public <U> CompletableFuture<u> applyToEither(
CompletionStage<? extends T> other , Function<? super T, U> fn);
public <U> CompletableFuture<U> applyToEitherAsync(
CompletionStage<? extends T> other , Function<? super T, U> fn);
public <U> CompletableFuture<U> applyToEitherAsync(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 CompletableFuture<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> runAfterEitherAsync(CompletionStage<?> other ,Runnable action,
Executor executor);

When any of the future tasks in the two tasks is completed, the task is executed.

  • applyToEither: One of the two tasks is executed, gets its return value, processes the task and has a new return value.
  • acceptEither: One of the two tasks is executed, get its return value, process the task, and there is no new return value.
  • runAfterEither: One of the two tasks is completed, there is no need to obtain the result of the future, process the task, and there is no return
    value.

2 examples

 //---任务组合--一个都完成---------------------------------------------------
    public static void applyToEitherAsync() throws ExecutionException, InterruptedException {
    
    
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("计算结果1:" + i);
            return i;
        }, executorService);
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程2:" + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("计算结果2:" + i);
            return i;
        }, executorService);

        CompletableFuture<Integer> future3 = future1.applyToEitherAsync(future2, (res1) -> {
    
    
            System.out.println("线程1结果....." + res1);
            System.out.println("线程3开始.....");
            return res1;
        }, executorService);

        System.out.println("线程3的结果是...." + future3.get());

    }

    public static void acceptEitherAsync() {
    
    
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("计算结果1:" + i);
            return i;
        }, executorService);
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程2:" + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("计算结果2:" + i);
            return i;
        }, executorService);

        future1.acceptEitherAsync(future2, (res1)-> {
    
    
            System.out.println("线程1结果....." + res1);
            System.out.println("线程3开始.....");
        }, executorService);

    }

    public static void runAfterEitherAsync() {
    
    
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("计算结果1:" + i);
            return i;
        }, executorService);
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程2:" + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("计算结果2:" + i);
            return i;
        }, executorService);

        future1.runAfterEitherAsync(future2, ()-> {
    
    
            System.out.println("线程3开始.....");
        }, executorService);

    }

Seven, multi-tasking combination

1 Function introduction

public static CompletableFuture<Void> allof(CompletableFuture<?>... cfs);
public static CompletableFuture<0bject> anyof(CompletableFuture<?>... cfs);
  • allof: wait for all tasks to complete
  • anyof: as long as there is one task completed

2 examples

 public static void allOf() throws ExecutionException, InterruptedException {
    
    
	CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1执行");
            return 10 / 2;
        }, executor);
        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2执行");
            return "hello";
        }, executor);
        CompletableFuture<String> future03 = future01.thenCombineAsync(future02,
                (result1, result2) -> {
                    System.out.println("任务3执行");
                    System.out.println("任务1返回值:" + result1);
                    System.out.println("任务2返回值:" + result2);
                    return "任务3返回值";
                }, executor);
        System.out.println(future03.get());


        CompletableFuture<Void> allOf = CompletableFuture.allOf(future01, future02, future03);
        allOf.get();// 阻塞等待所有任务完成
  }


public static void anyOf() throws ExecutionException, InterruptedException {
    
    
	CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1执行");
            return 10 / 2;
        }, executor);
        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2执行");
            return "hello";
        }, executor);
        CompletableFuture<String> future03 = future01.thenCombineAsync(future02,
                (result1, result2) -> {
                    System.out.println("任务3执行");
                    System.out.println("任务1返回值:" + result1);
                    System.out.println("任务2返回值:" + result2);
                    return "任务3返回值";
                }, executor);
        System.out.println(future03.get());


        CompletableFuture<Void> anyOf= CompletableFuture.allOf(future01, future02, future03);
        anyOf.get();// 阻塞等待任一任务完成,返回值是执行成功的任务返回值
  }

Eight, source code download

https://gitee.com/charlinchenlin/koo-erp

おすすめ

転載: blog.csdn.net/lovoo/article/details/130861594