springboot CompletableFuture grupo de subprocesos asíncronos

Este artículo ha participado en el evento "Ceremonia de creación de recién llegados" para comenzar juntos el camino de la creación de oro.

4 formas de inicializar async

1. Heredar subproceso
2. Implementar Runnable
3. Implementar interfaz invocable + Futuro (puede obtener el resultado de retorno y manejar excepciones después de jdk1.5)
4. Grupo de subprocesos [ExecutorService] (utilizado en el desarrollo real)

Modos 1 y 2: El subproceso principal no puede obtener el resultado de la operación del subproceso.
Modo 3: el subproceso principal puede obtener el resultado de la operación del subproceso, pero no es propicio para controlar los recursos del subproceso en el servidor. Puede provocar el agotamiento de los recursos del servidor.
Modo 4: el rendimiento del grupo de subprocesos es estable, los recursos están controlados, también se pueden obtener resultados de ejecución y se pueden detectar excepciones.

Siete parámetros del grupo de subprocesos:

  1. corePoolSize: [5] El número de subprocesos principales [siempre existe a menos que (allowCoreThreadTimeOut se recicle)]; grupo de subprocesos, listo 5 subprocesos después de la creación Subproceso subproceso = nuevo subproceso (); no iniciado. thread.start(); se ejecutará solo después de que la tarea se envíe al grupo de subprocesos;
  2. MaximumPoolSize: [200] Número máximo de subprocesos; recurso de control
  3. keepAliveTime: Hora de mantenerse con vida. Si el número actual de subprocesos es mayor que el número de núcleos. Liberar subprocesos inactivos (maximumPoolSize-corePoolSize). Siempre que el subproceso esté inactivo durante más tiempo que el keepAliveTime especificado.
  4. unidad: La unidad de tiempo.
  5. BlockingQueue workQueue: Cola de bloqueo. Si hay muchas tareas, las tareas actuales se colocarán en la cola. Siempre que haya subprocesos inactivos, vuelva a la cola y elimine nuevas tareas para continuar con la ejecución. new LinedBlockingDeque<>() : el valor predeterminado es el valor máximo de Integer, lo que causará memoria insuficiente
  6. threadFactory: fábrica de creación de hilos
  7. Manejador RejectedExecutionHandler: rechaza la columna de política, si la cola está llena, ejecuta la política de rechazo correspondiente
      7.1 DiscardOldestPolicy: descarta tareas antiguas que no se ejecutan cuando
      llegan tareas nuevas 7.4
      DiscardPolicy
      : descarta directamente sin lanzar excepciones

Orden de trabajo:

  1. Se crea el grupo de subprocesos, los subprocesos principales con la cantidad de núcleos están listos y están listos para aceptar tareas
  2. Cuando el núcleo esté lleno, las tareas entrantes se colocarán en la cola de bloqueo y el núcleo inactivo irá a la cola de bloqueo para ejecutar la tarea.
  3. Cuando la cola de bloqueo está llena, se abrirá un nuevo subproceso directamente para su ejecución, y el máximo solo se puede abrir hasta el número especificado por max.
  4. Cuando max está lleno, la tarea se rechaza con la estrategia RejectedExecutionHandler.
  5. La ejecución máxima se completa, hay mucho tiempo de inactividad, después del tiempo especificado keepAliveTime, se liberan los subprocesos de núcleo máximo

Ejecutores

  1. El núcleo newCachedThreadPool() es 0, todo se puede reciclar
  2. newFixedThreadPool() core de tamaño fijo = max; no se puede reciclar
  3. grupo de subprocesos newScheduledThreadPllo() para tareas cronometradas
  4. newSingleThreadExecutor() grupo de subprocesos de un solo subproceso, el fondo obtiene tareas para ejecutar una por una

1. Crea un objeto asíncrono

CompletableFuture proporciona cuatro métodos estáticos

//可以获取到返回值,可传入自定义线程池
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)
复制代码

prueba

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

2. Método de devolución de llamada cuando se completa el cálculo

//上一个任务完成和上一个任务用同一个线程
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);
复制代码

código de prueba

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

3. método handle (manejar y devolver cuando ocurre una excepción)

//和上一个任务使用同一个线程执行
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. prueba de manejo

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

5. Método de serialización de subprocesos (la tarea B solo se puede ejecutar después del resultado de ejecución de la tarea 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) 
复制代码

prueba

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. Dos combinaciones de tareas: ambas deben completarse

以下三种方式 两个任务都必须完成,才触发该任务
//组合两个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)
复制代码

prueba

        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. Dos tareas se completan una por una

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

prueba

		 /**
         * 两个任务有一个完成就执行三
         *
         */
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. Combinación multitarea

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

prueba

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());

复制代码

Supongo que te gusta

Origin juejin.im/post/7079649904724803591
Recomendado
Clasificación