ruoyi-vue使用线程池进行异步开发

1.异步线程池工具类

@Configuration
public class ThreadExecutorUtils
{
    // 核心线程池大小
    private int corePoolSize = 50;

    // 最大可创建的线程数
    private int maxPoolSize = 200;

    // 队列最大长度
    private int queueCapacity = 1000;

    // 线程池维护线程所允许的空闲时间
    private int keepAliveSeconds = 300;

    @Bean(name = "taskExecutor")
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //核心线程池大小
        executor.setCorePoolSize(corePoolSize);
        //最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        //队列容量
        executor.setQueueCapacity(queueCapacity);
        //活跃时间
        executor.setKeepAliveSeconds(keepAliveSeconds);
        //线程名字前缀
        executor.setThreadNamePrefix("ty-async-");
        // setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务
        // CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }


}

2.在需要使用异步操作的service实现类注入上面的类

  @Autowired
  private ThreadExecutorUtils threadPoolTaskExecutor;

3.使用线程池进行异步操作

  Executor executor = threadPoolTaskExecutor.getAsyncExecutor();
  //addVisitHistory为本类中定义的一个异步执行的业务方法
  executor.execute(() -> addVisitHistory(userId, spuId));

需要注意的地方:如果项目采用多数据源,在异步线程中,由于多数据源的动态切换通常依赖于线程本地变量(如 ThreadLocal),而异步线程会丢失主线程的上下文(包括 ThreadLocal 中的数据源信息),因此需要额外的处理来确保数据源的一致性。

下面介绍一种示例处理方法:

// 获取当前数据源
String currentDataSource = DataSourceContextHolder.getDataSource();

// 创建异步任务
CompletableFuture.runAsync(() -> {
    // 在异步线程中设置数据源
    DataSourceContextHolder.setDataSource(currentDataSource);
    try {
        // 执行业务逻辑
        someService.doSomething();
    } finally {
        // 清除数据源
        DataSourceContextHolder.clearDataSource();
    }
}, executor);

优点

  • 简单直接,易于理解。

  • 适用于少量异步任务的场景。

缺点

  • 需要手动传递和设置数据源,代码侵入性较强。

  • 如果异步任务嵌套较多,容易遗漏数据源的设置

你可能感兴趣的:(ruoyi)