关于ExecutorFuture 多线程,使用编写例子

170 阅读16分钟

关于ExecutorFuture 多线程 同步与异步编程的基本概念,使用异步编排的原因

  • 同步编程:指程序执行某个任务时,当前线程会被阻塞,直到任务完成。在这种模式下,后续代码需要等待前一个任务的完成。

  • 异步编程:在执行任务时,当前线程不会被阻塞,任务会交给其他线程来执行。任务完成后,通常通过回调或通知的方式来处理结果。

  • 提高效率:在复杂的操作如商品详情页查询中,涉及多个远程调用(RPC),异步可以减少等待时间。例如,使用异步可以将响应时间从3.5秒减少到1.5秒。

  • 任务依赖管理:在异步化操作时,需要确保任务的依赖关系,例如在获取用户信息时可能需要先获取分类信息。

一. 定义一个多线程的返回结果对象接口类

/** 多线程并发返回结果对象接口类实现**/
public interface FutureResponse {
}

二. 定义一个多线程构建具体的并发任务接口类

/** 多线程构建具体的并发任务接口类**/
public interface FutureRequest {
}

三. 定义一个多线程构建具体的线程接口类

/** 多线程构建具体的线程接口类**/
public interface FutureCallableOrder<T> extends Callable<T>, Ordered {
}

四. 抽象一个多线程具体的实现抽象类



import org.apache.skywalking.apm.toolkit.trace.TraceContext;

/**
 * @author 作者 : suven
 * @date 创建时间: 2023-12-11
 * @version 版本: v1.0.0
 * <pre>
 *
 *  @description (说明):
 * </pre>
 * <pre>
 * 修改记录
 *    修改后版本:     修改人:  修改日期:     修改内容:
 * </pre>
 **/

public abstract class AbstractFutureCallableRoute<R extends FutureRequest,V extends FutureResponse > implements FutureCallableOrder<V>{
    private final int order;
    private final R request;
    private final String traceId;

    public AbstractFutureCallableRoute(int order, R requestParameter) {
        this.order = order;
        this.request = requestParameter;
        this.traceId = TraceContext.traceId();
    }
    /**
     * Get the order value of this object.
     * <p>Higher values are interpreted as lower priority. As a consequence,
     * the object with the lowest value has the highest priority (somewhat
     * analogous to Servlet {@code load-on-startup} values).
     * <p>Same order values will result in arbitrary sort positions for the
     * affected objects.
     *
     * @return the order value
     * @see #HIGHEST_PRECEDENCE
     * @see #LOWEST_PRECEDENCE
     */
    @Override
    public int getOrder() {
        return order;
    }

    public R getRequest(){
        return request;
    }
    /**
     * 任务的具体过程,一旦任务传给ExecutorService的submit方法,
     * 则该方法自动在一个线程上执行
     */
    public V call() throws Exception {
       callTraceId();
       return calling();

    }

    public void callTraceId(){
        TraceContext.putCorrelation("traceId",traceId);
    }

    public abstract V calling() throws Exception;


}


五.静态方法callFuture,用于执行多个并发任务。它接收一个FutureCallableRoute对象的列表作为参数,将每个任务提交给线程池进行执行,并将执行结果保存在Future对象的列表中

/** 该类包含了一个静态方法callFuture,用于执行多个并发任务。它接收一个FutureCallableRoute对象的列表作为参数,将每个任务提交给线程池进行执行,并将执行结果保存在Future对象的列表中。然后,通过遍历Future列表,并使用get()方法获取每个任务的执行结果,并将结果存储在结果列表中。最后,关闭线程池。
以上就是这段代码的简要介绍。它提供了一种利用线程池并发执行任务并获取结果的方式。通过使用ExecutorService和Future接口
**/


import com.alibaba.fastjson.JSON;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @author 作者 : suven
 * date 创建时间: 2023-12-08
 * @version 版本: v1.0.0
 * <pre>
 *
 *  description (说明):
 * </pre>
 * <pre>
 * 修改记录
 *    修改后版本:     修改人:  修改日期:     修改内容:
 * </pre>
 **/
@Slf4j
public class ExecutorFuture {


    private static class SingletonFuture {
        static ExecutorFuture INSTANCE = new ExecutorFuture();
    }
    /**
     * 线程池初始化方法
     *
     * corePoolSize 核心线程池大小----10
     * maximumPoolSize 最大线程池大小----1000
     * keepAliveTime 线程池中超过corePoolSize数目的空闲线程最大存活时间----30+单位TimeUnit
     * TimeUnit keepAliveTime时间单位----TimeUnit.MINUTES
     * workQueue 阻塞队列----new ArrayBlockingQueue<Runnable>(10)====10容量的阻塞队列
     * threadFactory 新建线程工厂----new CustomThreadFactory()====定制的线程工厂
     * rejectedExecutionHandler 当提交任务数超过maxmumPoolSize+workQueue之和时,
     *                    即当提交第41个任务时(前面线程都没有执行完,此测试方法中用sleep(100)),
     *                           任务会交给RejectedExecutionHandler来处理
     */

    private final static ExecutorService executors = new ThreadPoolExecutor(
            10,  20, 5,
            TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(100000),
            new ThreadFactoryBuilder().setNameFormat("pick-logger-worker-%d").build());

    private ExecutorFuture(){}

    public ExecutorFuture instance(){
        return SingletonFuture.INSTANCE;
    }


    public static enum FutureErrorCode {
       SYS_COMPLETABLE_FUTURE_TIMEOUT(1100057, "异步线程调用业务超时异常[ %s ]"),
       SYS_COMPLETABLE_FUTURE_EXCEPTION(1100058, "异步线程调用业务超时异常[ %s ]"),
       SYS_COMPLETABLE_FUTURE_INTERRUPTED(1100059, "异步线程恢复线程中断状态[ %s ]"),
       SYS_COMPLETABLE_BUILD_EXCEPTION(1100060, "异步线程创建异常[ %s ]"),
       SYS_COMPLETABLE_FUTURE_LIST_EMPTY(1100061, "callableFutureList cannot be null or empty"),
       ;
       private int code;
       private String msg;
       FutureErrorCode(int code, String msg) {
           this.code = code;
           this.msg = msg;
       }
       public String getMsg() {
           return msg;
       }

   }



    public static <R,F extends Callable<R>>  List<R> callFuture(List<F> futureResultList) {
        List<Future<R>> futureList = new ArrayList<>();
        List<R> resultList = new ArrayList<>();
        //创建10个任务并执行
        futureResultList.forEach(callable -> {
            //使用ExecutorService执行Callable类型的任务,并将结果保存在future变量中
            Future<R>  future = executors.submit(callable);
            //将任务执行结果存储到List中
            futureList.add(future);
        });

        futureList.forEach(future ->{
            try{
                while(!future.isDone()){

                };//Future返回如果没有完成,则一直循环等待,直到Future返回完成
                R result = future.get();
                //各个线程(任务)执行的结果
                resultList.add(result);
            }catch(Exception e){
                log.info("callFutureMap futureResultList[{}] , Exception:[{}] ",JSON.toJSONString(futureResultList),e);
            }
        } );
        return resultList;
    }

    public static <T extends FutureResponse,F extends Callable<T>> Map<Integer, T> callFutureMap(List<F> futureResultList) {
        List<Future<T>> futureList = new ArrayList<>();
        Map<Integer, T> resultMap = new TreeMap<>();
        //创建10个任务并执行
        futureResultList.forEach(callable -> {
            //使用ExecutorService执行Callable类型的任务,并将结果保存在future变量中
            Future<T>  future = executors.submit(callable);
            //将任务执行结果存储到List中
            futureList.add(future);
        });

        futureList.forEach(future ->{
            try{
                while(!future.isDone());//Future返回如果没有完成,则一直循环等待,直到Future返回完成
                T result = future.get();
                log.info("callFutureMap futureResultList[{}]  ",JSON.toJSONString(result));
                //各个线程(任务)执行的结果
                resultMap.put(result.getOrder(),result);
            }catch (RuntimeException runtimeException){
                throw runtimeException;
            } catch(Exception e){
                log.info("callFutureMap futureResultList[{}] , Exception:[{}] ",JSON.toJSONString(futureResultList),e);
            }
        } );
        return resultMap;
    }

    public static <T extends FutureResponse,F extends Callable<T>> Map<Integer, T> callFutureMapEx(List<F> futureResultList) {
        List<Future<T>> futureList = new ArrayList<>();
        Map<Integer, T> resultMap = new TreeMap<>();
        //创建10个任务并执行
        futureResultList.forEach(callable -> {
            //使用ExecutorService执行Callable类型的任务,并将结果保存在future变量中
            Future<T>  future = executors.submit(callable);
            //将任务执行结果存储到List中
            futureList.add(future);
        });
        futureList.forEach(future ->{
            try {
                while (!future.isDone()) ;//Future返回如果没有完成,则一直循环等待,直到Future返回完成
                T result = future.get();
                log.info("callFutureMap futureResultList[{}]  ", JSON.toJSONString(result));
                //各个线程(任务)执行的结果
                resultMap.put(result.getOrder(), result);
            } catch (RuntimeException runtimeException){
                    throw runtimeException;
            }catch(Exception e){
                log.info("callFutureMap futureResultList[{}] , Exception:[{}] ",JSON.toJSONString(futureResultList),e);
            }
        } );
        return resultMap;
    }

    /**
     * 提交Callable任务列表到执行器服务,并返回Future对象列表
     * 该方法允许批量提交Callable任务,每个任务代表一个异步计算
     * 使用泛型参数R和F,其中R是计算结果类型,F是实现了Callable接口的类型
     *
     * @param futureResultList 包含一系列实现了Callable接口的实例列表
     *                         列表中的每个元素代表一个可以异步执行的任务
     * @return 返回一个包含Future对象的列表,每个Future对象代表一个提交的任务
     * 可以通过Future对象来获取任务执行结果或取消任务
     */
    public static <R, F extends Callable<R>> List<Future<R>> submitCallables(List<F> futureResultList) {
        // 创建一个空的Future列表,用于存储提交任务后返回的Future对象
        List<Future<R>> futureList = new ArrayList<>();

        // 遍历Callable任务列表,提交每个任务到执行器服务
        futureResultList.forEach(callable -> {
            // 提交任务并获取Future对象
            Future<R> future = executors.submit(callable);
            // 将Future对象添加到列表中
            futureList.add(future);
        });

        // 返回包含所有任务的Future对象列表
        return futureList;
    }

    /**
     * 异步执行一个 Callable 任务,并根据参数决定是否获取任务结果。
     * 该方法使用 CompletableFuture.runAsync 和 FutureTask 来实现异步任务的执行,
     * 并支持超时控制和异常处理。
     *
     * @param executor       用于执行任务的线程池。负责管理任务的异步执行。
     * @param callableFuture 需要执行的 Callable 任务,任务执行完成后会返回一个结果。
     * @param parameter      任务执行的参数配置,包含是否需要获取结果、超时时间以及业务描述等信息。
     * @return 如果参数允许获取结果,则返回任务的执行结果;否则返回 null。
     * @throws RuntimeException 如果任务执行超时或发生其他异常,会抛出业务异常,异常信息由参数中的业务描述生成。
     */
    public static <V>V completableFutureRun(ExecutorService executor, Callable<V> callableFuture, FutureParameter parameter) {

        if (callableFuture == null ){
            throw  new RuntimeException(FutureErrorCode.SYS_COMPLETABLE_FUTURE_LIST_EMPTY.getMsg());
        }
        // 将 Callable 包装为 FutureTask,以便通过 CompletableFuture.runAsync 执行任务
        FutureTask<V> futureTask = new FutureTask<>(callableFuture);

        // 使用 CompletableFuture.runAsync 方法异步执行任务
        CompletableFuture.runAsync(futureTask, executor);

        // 如果参数为空或不需要获取结果,则直接返回 null
        if (parameter == null || !parameter.isFutureResult()) {
            return null;
        }

        // 获取任务结果,支持超时控制
        V result = null;
        try {
            // 根据参数中的超时时间决定如何获取任务结果
            if (parameter.getTimeout() > 0) {
                result = futureTask.get(parameter.getTimeout(), TimeUnit.SECONDS);
            } else {
                result = futureTask.get();
            }
            return result;
        } catch (TimeoutException e) {
            // 如果任务执行超时,抛出业务异常,异常信息包含业务描述
            throw new RuntimeException(FutureErrorCode.SYS_COMPLETABLE_FUTURE_TIMEOUT.getMsg());
        } catch (Exception e) {
            // 捕获其他异常,抛出业务异常,异常信息包含具体错误消息
            throw new RuntimeException(FutureErrorCode.SYS_COMPLETABLE_FUTURE_EXCEPTION.getMsg());
        }
    }
    /**
     * 批量异步执行 Callable 任务列表,并根据参数决定是否获取任务结果。
     * 该方法使用 CompletableFuture 和 FutureTask 实现异步任务的批量执行,
     * 并支持超时控制和异常处理。
     *
     * @param executor            用于执行任务的线程池。负责管理任务的异步执行。
     * @param callableFutureList   需要执行的 Callable 任务列表,每个任务代表一个异步计算。
     *                             列表不能为空或 null。
     * @param parameter            任务执行的参数配置,包含是否需要获取结果、超时时间以及业务描述等信息。
     * @return 如果参数允许获取结果,则返回包含所有任务执行结果的列表;
     *         如果参数无效或未启用 futureResult,则返回空列表。
     * @throws IllegalArgumentException 如果 callableFutureList 为 null 或空。
     * @throws RuntimeException         如果任务执行超时或发生其他异常,会抛出业务异常。
     * 方法说明
     * 参数校验:
     * 确保 callableFutureList 不为 null 且不为空。
     * 如果 parameter 为 null 或未启用 futureResult,直接返回空列表。
     * 任务提交:
     * 使用 CompletableFuture.supplyAsync 提交任务到线程池,并将每个任务包装为 CompletableFuture 对象。
     * 等待任务完成:
     * 使用 CompletableFuture.allOf 等待所有任务完成。
     * 如果任务执行过程中发生异常且允许中断,则抛出自定义业务异常。
     * 结果收集:
     * 遍历所有 CompletableFuture 对象,获取任务结果。
     * 支持超时控制,处理超时、中断和其他异常情况。
     * 异常处理:
     * 超时异常:抛出业务异常,异常信息包含业务描述。
     * 中断异常:恢复线程中断状态并抛出业务异常。
     * 其他异常:捕获并抛出业务异常,异常信息包含具体错误消息。
     */
    public static <V> boolean completableFutureRunList( ExecutorService executor, List<Callable<V>> callableFutureList, FutureParameter parameter) {

        // 参数校验:确保 callableFutureList 不为 null 且不为空
        if (callableFutureList == null || callableFutureList.isEmpty()) {
            throw  new RuntimeException(FutureErrorCode.SYS_COMPLETABLE_FUTURE_LIST_EMPTY.getMsg());
        }
        // 使用 Stream 模式提交任务并存储 CompletableFuture 对象
        @NotNull
        List<CompletableFuture<Void>> futures = callableFutureList.stream()
            .map(callableFuture ->  CompletableFuture.runAsync(new FutureTask<>(callableFuture), executor)).collect(Collectors.toList());
        // 等待所有任务完成,如果发生异常且允许中断,则抛出自定义业务异常
        try {
            // 如果参数无效(parameter 为 null 或未启用 futureResult),直接返回空列表
            if (parameter != null &&parameter.isFutureResult()) {
                CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
            }
        } catch (CompletionException e) {
            if (parameter.isInterrupt()) {
                throw  new RuntimeException(FutureErrorCode.SYS_COMPLETABLE_FUTURE_EXCEPTION.getMsg(),e);
            }
        }
        return true;
    }


    /**
     * 执行一组异步任务并收集结果。
     *
     * @param executor          用于执行异步任务的线程池。
     * @param callableFutureList 包含 Callable 任务的列表,每个任务将被提交到线程池中执行。
     *                           不能为 null 或空列表。
     * @param parameter          控制任务执行行为的参数对象,包含是否中断、超时时间等信息。
     *                           如果为 null 或未启用 futureResult,则直接返回 null。
     * @param <V>                任务返回值的类型。
     * @param <Future>           继承自 Callable 的任务类型。
     * @return 如果参数有效且任务成功完成,则返回包含所有任务结果的列表;
     *         如果参数无效或任务未启用 futureResult,则返回 null。
     * @throws IllegalArgumentException 如果 callableFutureList 为 null 或空。
     * @throws CompletionException       如果任务执行过程中发生异常且参数允许中断。
     */
    public static <V, Future extends Callable<V>> List<V>  completableFutureList(ExecutorService executor, List<Future> callableFutureList, FutureParameter parameter) {
        // 参数校验:确保 callableFutureList 不为 null 且不为空
        // 参数校验:确保 callableFutureList 不为 null 且不为空
        if (callableFutureList == null || callableFutureList.isEmpty()) {
            throw   new RuntimeException(FutureErrorCode.SYS_COMPLETABLE_FUTURE_LIST_EMPTY.getMsg());
        }

        // 使用 Stream 模式提交任务并存储 CompletableFuture 对象
        List<CompletableFuture<V>> futures = callableFutureList.stream()
                .map(callableFuture -> CompletableFuture.supplyAsync(() -> {
                    try {
                        return callableFuture.call();
                    } catch (Exception e) {
                        throw  new RuntimeException(FutureErrorCode.SYS_COMPLETABLE_BUILD_EXCEPTION.getMsg(),e);
                    }
                }, executor))
                .collect(Collectors.toList());

        // 等待所有任务完成,如果发生异常且允许中断,则抛出自定义业务异常
        try {
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        } catch (CompletionException e) {
            if (parameter.isInterrupt()) {
                throw  new RuntimeException(FutureErrorCode.SYS_COMPLETABLE_FUTURE_EXCEPTION.getMsg(),e);
            }
        }

        // 如果参数无效(parameter 为 null 或未启用 futureResult),直接返回 null
        if (parameter == null || !parameter.isFutureResult()) {
            return null;
        }

        // 收集任务结果,处理超时、中断和其他异常情况
        List<V> resultList = new ArrayList<>();
        for (CompletableFuture<V> future : futures) {
            try {
                V result;
                if (parameter.getTimeout() > 0) {
                    result = future.get(parameter.getTimeout(), TimeUnit.SECONDS);
                } else {
                    result = future.get();
                }
                resultList.add(result);
            } catch (TimeoutException e) {
                if (parameter.isInterrupt()) {
                    throw  new RuntimeException(FutureErrorCode.SYS_COMPLETABLE_FUTURE_TIMEOUT.getMsg(), e);
                }
            } catch (InterruptedException e) {
                if (parameter.isInterrupt()) {
                    Thread.currentThread().interrupt(); // 恢复线程中断状态
                    throw  new RuntimeException(FutureErrorCode.SYS_COMPLETABLE_FUTURE_INTERRUPTED.getMsg(),e);
                }
            } catch (Exception e) {
                if (parameter.isInterrupt()) {
                    throw  new RuntimeException(FutureErrorCode.SYS_COMPLETABLE_FUTURE_EXCEPTION.getMsg(),e);
                }
            }
        }

        return  resultList;
    }

}

六. 线程线程跟踪实现

/**
     *  业务传递当前线程线路id,如何为空时,初始化uuid链路id
     */
    public static String initTraceId(){
        String traceId = TraceContext.traceId();
        if (Objects.isNull(traceId)){
            traceId = UUID.randomUUID().toString();
        }
        TraceContext.putCorrelation("traceId",traceId);
        return traceId;
    }

2.线程控制参数对象类


import lombok.Data;

@Data
public  class FutureParameter {
    // 超时时间,单位为秒
    private long timeout;
    // 是否返回结果
    private boolean isFutureResult;
    // 业务描述
    private String bizDesc;
    //线程异常是否中断
    private boolean isInterrupt = true;


    public static FutureParameter build(long timeout, boolean isFutureResult, String bizDesc) {
        FutureParameter parameter = new FutureParameter();
        parameter.setTimeout(timeout);
        parameter.setFutureResult(isFutureResult);
        parameter.setBizDesc(bizDesc);
        return parameter;
    }
    public static FutureParameter build(String bizDesc) {
        FutureParameter parameter = new FutureParameter();
        parameter.setTimeout(3000);
        parameter.setFutureResult(false);
        parameter.setBizDesc(bizDesc);
        parameter.setInterrupt(true);
        return parameter;
    }
}

  • 在创建线程(FutureCallableRoute)继承类的构造器中执行initTraceId()初始化路线唯一字符串
  • 在执行运行线程中,输入以下代码,即可
 TraceContext.putCorrelation("traceId",traceId);
 

七.关于ExecutorFuture类的结构和功能:

  1. . ExecutorFuture类是一个单例类,通过私有的构造函数和静态内部类实现了单例模式。这确保了只有一个ExecutorFuture实例存在。

  2. ExecutorFuture类包含了一个静态的ExecutorService对象executors,它是一个线程池。线程池在代码中通过ThreadPoolExecutor进行初始化,指定了核心线程数、最大线程数、线程空闲时间等参数。

  3. ExecutorFuture类的callFuture方法是用于执行多个并发任务的关键方法。它接收一个FutureCallableRoute对象的列表futureResultList作为参数,表示要执行的并发任务列表。

  4. callFuture方法中,首先创建了两个空列表:futureList用于存储Future对象,resultList用于存储任务的执行结果。

  5. 然后,通过遍历futureResultList列表,对于每个FutureCallableRoute对象,使用线程池的submit方法提交任务并返回一个Future对象。将这些Future对象添加到futureList中。

  6. 接下来,使用futureList列表进行遍历,对于每个Future对象,通过isDone方法判断任务是否完成,如果任务未完成,则通过循环等待,直到任务完成。

  7. 当任务完成后,通过get方法获取任务的执行结果,并将结果存储在resultList中。

  8. 最后,关闭线程池,通过调用executors.shutdown()方法来实现。

这段代码的目的是实现多线程并发执行任务,并且能够按照一定的顺序获取任务的执行结果。它使用了Java的线程池和Future接口来管理和控制任务的执行,并通过Future对象获取任务的执行结果。

在使用这段代码时,您需要提供具体的实现类来继承FutureCallableRoute,并实现其中的call方法,用于定义具体的任务逻辑。然后,将这些实现类对象添加到futureResultList中,并调用callFuture方法来执行并发任务。

请注意,代码中的线程池参数和队列大小等可以根据您的需求进行调整。同时,您也可以根据具体的业务场景对代码进行修改和扩展。

八. CompletableFuture 异步编排。先阐述了同步和异步概念,指出使用异步编排的原因。接着详细讲解了 CompletableFuture 的学习,包括多种方法及对比。然后通过实战案例展示其应用,最后说明了异步编排的使用场景,如并行调用微服务、批量处理任务等,强调其在优化性能和处理复杂流程中的作用。

1. Future和CompletableFuture

  • Future的局限性

    • 结果获取方法

      future.get()

      是阻塞的。

    • 任务组合功能不足,难以处理复杂异步任务链。

    • 异常处理复杂。

  • CompletableFuture的优势

    • 支持非阻塞操作,并提供

      thenApplythenAccept

      等方法来执行后续操作。

    • 便捷的任务组合能力,如

      thenCombineallOf

    • 异常处理简洁,提供

      exceptionally

      等方法。

    • 可构建复杂的异步流程,提高代码可读性与维护性。

2. CompletableFuture的使用 在 JDK 8 中引入,提供了更强大和灵活的异步编程支持。它不仅可以用来表示异步计算的结果,还提供了许多方便的方法来处理异步任务的执行和结果处理。以下是 CompletableFuture 的一些主要用途:

  • 核心方法

    • 异步计算runAsync:启动不需要返回值的异步任务,用于记录日志等。

    • 非阻塞操作supplyAsync:启动需要返回结果的异步任务,如计算或数据获取。

    • 组合多个异步任务CompletableFuture 提供了方法来组合多个异步任务,例如 whenCompleteexceptionally :处理任务完成及异常情况,相当于Java 中的then和catch。

    • 阻塞操作thenApplythenAccept :前者处理结果并返回新值,后者处理结果但不返回新值。

    • 处理异常exceptionally :类似于 Vue 中发起异步请求之后的 catch 方法,只有当任务发生异常时才会执行,可以用于处理异步任务中的异常,并返回一个替代结果。。

    • Async后缀thenApplyAsync

3. 实战案例

具体的使用例子:



public class FutureExceptionally {
    public static void main(String[] args) throws Exception {
        System.out.println("在主线程打印日志,启动异步运行异常线程--开始");
       runAsyncException();
         System.out.println("在主线程打印日志,启动异步运行异常线程--结果");
        SleepUtils.sleep(3);
    }
    //发起一个异步请求
    public static void runAsyncException() {
        CompletableFuture.runAsync(new Runnable() {
            @Override
            public void run() {
             System.out.println("在异步线程中打印日志,异步运行中,抛出运行异常线程");
              //int result =100/0;
             throw new RuntimeException("异步线程中,主动抛出运行异常");
            }
        }).whenComplete(new BiConsumer<Void, Throwable>() {
            @Override
            public void accept(Void acceptVal, Throwable throwable) {
                System.out.println("执行异步之后通过whenComplete请求参数"+acceptVal);
                System.out.println("执行异步之后通过whenComplete抛出异常值"+throwable);
            }
        }).exceptionally(new Function<Throwable, Void>() {
            @Override
            public Void apply(Throwable throwable) {
                System.out.println("执行异步之后exceptionally异常值"+throwable);
                 System.out.println("执行异步之后,处理期望要处理的业务实现");
                return null;
            }
        });
    }

}

4. 异步编排的应用场景

  • 并行调用微服务:如电商平台需要同时调用多个服务。
  • 异步批量任务处理:例如批量用户数据的导入和校验。
  • 用户请求的异步处理:从多个数据源获取并合并返回。
  • 复杂工作流执行:步骤多且需异步执行的业务流程。

希望这些信息能够帮助您更好地理解这段代码。如果您有任何进一步的问题,请随时提问。