springboot CompletableFuture asynchronous thread pool

This article has participated in the "Newcomer Creation Ceremony" event to start the road of gold creation together.

4 ways to initialize async

1. Inherit Thread
2. Implement Runnable
3. Implement Callable interface + Future (you can get the return result and handle exceptions after jdk1.5)
4. Thread pool [ExecutorService] (used in actual development)

Modes 1 and 2: The main thread cannot obtain the operation result of the thread.
Mode 3: The main thread can obtain the operation result of the thread, but it is not conducive to controlling the thread resources in the server. Can lead to exhaustion of server resources.
Mode 4: Thread pool performance is stable, resources are controlled, execution results can also be obtained, and exceptions can be caught.

Seven parameters of the thread pool:

  1. corePoolSize: [5] The number of core threads [always exists unless (allowCoreThreadTimeOut will be recycled)]; thread pool, ready 5 threads after creation Thread thread = new Thread(); not started. thread.start(); will be executed only after the task is submitted to the thread pool;
  2. maximumPoolSize : [200] Maximum number of threads; control resource
  3. keepAliveTime : Time to keep alive. If the current number of threads is greater than the number of cores. Release idle threads (maximumPoolSize-corePoolSize). As long as the thread is idle for longer than the specified keepAliveTime.
  4. unit : The unit of time.
  5. BlockingQueue workQueue: Blocking queue. If there are many tasks, the current tasks will be placed in the queue. As long as there are idle threads, go back to the queue and take out new tasks to continue execution. new LinedBlockingDeque<>() : The default is the maximum value of Integer, which will cause insufficient memory
  6. threadFactory: thread creation factory
  7. RejectedExecutionHandler handler: Rejection policy column, if the queue is full, execute the corresponding rejection policy
      7.1 DiscardOldestPolicy: Discard old tasks that are not executed when new tasks
      come
      in
      7.4 DiscardPolicy: Discard directly without throwing exceptions

Working order:

  1. The thread pool is created, the core threads with the number of cores are ready, and they are ready to accept tasks
  2. When the core is full, the incoming tasks will be placed in the blocking queue, and the idle core will go to the blocking queue to get the task execution.
  3. When the blocking queue is full, a new thread will be opened directly for execution, and the maximum can only be opened to the number specified by max.
  4. When max is full, the task is rejected with the RejectedExecutionHandler strategy.
  5. The max execution is completed, there is a lot of idle time, after the specified time keepAliveTime, the max-core threads are released

Executors

  1. newCachedThreadPool() core is 0, all can be recycled
  2. newFixedThreadPool() fixed size core= max; can not be recycled
  3. newScheduledThreadPllo() thread pool for timed tasks
  4. newSingleThreadExecutor() single-threaded thread pool, the background gets tasks to execute one by one

1. Create an asynchronous object

CompletableFuture provides four static methods

//可以获取到返回值,可传入自定义线程池
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)
//没有返回值,可传入自定义线程池
public static CompletableFuture<Void> runAsync(Runnable runnable)
public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor)
复制代码

test

public static ExecutorService service = Executors.newFixedThreadPool(10);
  //没有返回值
        CompletableFuture.runAsync(()->{
            System.out.println("异步任务成功完成了");
        },service);
        //空入参只有返回值
        CompletableFuture<String> stringCompletableFuture = CompletableFuture.supplyAsync(() -> {
            return "返回值";
        }, service);
复制代码

2. Callback method when calculation is completed

//上一个任务完成和上一个任务用同一个线程
public CompletableFuture<T> whenComplete(BiConsumer<? super T, ? super Throwable> action);
//交给线程池重新启动一个线程
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action);
//任务执行完成后(只能感知)
public CompletableFuture<T> whenComplete(BiConsumer<? super T, ? super Throwable> action);
//感知异常同时修改返回值
public CompletableFuture<T> exceptionally(Function<Throwable, ? extends T> fn);
复制代码

test code

 CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            return 10;
        }, service).whenComplete((res,excption)->{
            //虽然能得到异常消息但是不能修改返回结果
            System.out.println("异步任务成功完成了"+res+"或者异常:"+excption);
        }).exceptionally(throwable ->{
            //处理异常并可以数据修改返回值
            return 0;
       });
复制代码

3. handle method (handle and return when an exception occurs)

//和上一个任务使用同一个线程执行
public <U> CompletableFuture<U> handle(BiFunction<? super T, Throwable, ? extends U> fn)
//默认线程池开启线程执行
public <U> CompletableFuture<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn)
//指定自己的线程池开启线程执行
public <U> CompletableFuture<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn, Executor executor)
复制代码

4. handle test

       //方法执行完成后的处理不论成功还是失败
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            return 10;
        }, service).handle((res,thr)->{
            //未出现异常 当然这里可以不写 为了掩饰
           if(res!=null){
               return 0;
           }
           //出现异常
           if(thr!=null){
               return 1;
           }
           return 0;
        });
复制代码

5. Thread serialization method (task B can only be executed after the execution result of task A)

//A-->B-->C 感知上一步结果并返回最后一次的结果
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)

//B可以感知到A的返回值 
public CompletableFuture<Void> thenAccept(Consumer<? super T> action)
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action) 
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action,
                                                   Executor executor)
//A->完成后(有Async开启新的线程没有就是和A一个线程)感知不到上一步的执行结果                                                   
public CompletableFuture<Void> thenRun(Runnable action) 
public CompletableFuture<Void> thenRunAsync(Runnable action) 
public CompletableFuture<Void> thenRunAsync(Runnable action, Executor executor) 
复制代码

test

CompletableFuture<Void> voidCompletableFuture = CompletableFuture.supplyAsync(() -> {
            //任务A
            return 10;
        }, service).thenRunAsync(() -> {
            //感知不到 任务A的结果
        },service);
复制代码
CompletableFuture<Void> voidCompletableFuture = CompletableFuture.supplyAsync(() -> {
            //任务A
            return 10;
        }, service).thenAcceptAsync((res) -> {
            //可以感知到任务A的结果,但是不能返回数据
            int i = res / 2;
        },service);
复制代码
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            //任务A
            return 10;
        }, service).thenApplyAsync((res) -> {
        //返回值以最后一次返回为准
            return 10 + res;
        }, service);
复制代码

6. Two task combinations - both must be completed

以下三种方式 两个任务都必须完成,才触发该任务
//组合两个future,获取两个future 任务的返回结果,并返回当前任务的返回值
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<? 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) 

//组合两个future,获取两个future 任务的返回结果,然后处理任务,没有返回值。
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 U> action, Executor executor) 
        
//组合两个future ,不需要获取future的结果,只需要两个 future处理完成后处理该任务        
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)
复制代码

test

        CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            //任务A
            System.out.println(Thread.currentThread().getId());
            System.out.println("任务一结束");
            return 10/2;
        }, service);
        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            //任务A
            System.out.println(Thread.currentThread().getId());
            System.out.println("任务二结束");
            return "future02";
        }, service);
        //不能感知到结果
        CompletableFuture<Void> future03void = future01.runAfterBothAsync(future02, () -> {
            System.out.println("任务三执行结束");
        }, service);
        //可以感知获取到前两个任务结果
        CompletableFuture<Void> future03No = future01.thenAcceptBothAsync(future02, (res1, res2) -> {
            System.out.println("任务三执行结束");
        }, service);
        CompletableFuture<String> future03 = future01.thenCombineAsync(future02, (res1, res2) -> {
            System.out.println("任务三执行结束");
            return res1 + "-" + res2;
        }, service);
复制代码

7. Two tasks are completed one by one

//两个任务有一个执行完成,获取它的返回值,处理任务并有新的返回值
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)
//两个任务有一个执行完成,不需要获取future的结果,处理任务 ,也没有返回值
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)
复制代码

test

		 /**
         * 两个任务有一个完成就执行三
         *
         */
CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            //任务A
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getId());
            System.out.println("任务一结束");

            return 10/2;
        }, service);
        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            //任务A
            System.out.println(Thread.currentThread().getId());

            System.out.println("任务二结束");
            return "future02";
        }, service);
        //不感知结果,自己也没有返回值
        future01.runAfterEitherAsync(future02,()->{
            System.out.println("任务三执行结束");
        },service);
        //感知到结果,自己没有返回值
        future01.acceptEitherAsync(future02,(res)->{
            //感知到线程已经处理完成的结果
            System.out.println("任务三执行结束"+res);
        },service);
        //感知到结果并返回自己的返回值
        CompletableFuture<String> stringCompletableFuture = future01.applyToEitherAsync(future02, res -> {
            return "任务三结果" + res;
        }, service);
复制代码

8. Multitasking combination

//等待所有任务完成
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)
//只要有一个任务完成
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
复制代码

test

CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            //任务A
            System.out.println(Thread.currentThread().getId());
            System.out.println("任务一结束");

            return 10/2;
        }, service);
        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            //任务A
            System.out.println(Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务二结束");
            return "future02";
        }, service);
        //此方法是阻塞式等待不建议在这使用
        //future01.get();
        //future02.get();
        
		//等待所有任务完成不会阻塞
        CompletableFuture<Void> allOf= CompletableFuture.allOf(future01, future02);
        //等待所有的都完成(两个任务同时执行)
        allOf.get();
        log.info("end");
        System.out.println(future02.get()+""+future01.get());
        //只有一个完成
        CompletableFuture<Object> anyOf= CompletableFuture.anyOf(future01, future02);
        anyOf.get();
        System.out.println(anyOf.get());

复制代码

Guess you like

Origin juejin.im/post/7079649904724803591