SpringBoot使用Async注解实现异步线程

发布时间 2023-12-15 19:30:04作者: bug毁灭者

1、启动类增加@EnableAsync注解

2、yml增加配置

spring:
  task:
    execution:
      pool:
        max-size: 8
        core-size: 8
        keep-alive: 60
        queue-capacity: 1000
      thread-name-prefix: Asnyc-task-calc-

3、编写配置类AsyncTaskConfig

import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.Executor;


@Configuration
@Slf4j
public class AsyncTaskConfig implements AsyncConfigurer {

    @Value("${spring.task.execution.pool.max-size}")
    private Integer maxSize;

    @Value("${spring.task.execution.pool.core-size}")
    private Integer coreSize;

    @Value("${spring.task.execution.pool.keep-alive}")
    private Integer keepAlive;

    @Value("${spring.task.execution.pool.queue-capacity}")
    private Integer queueCapacity;

    @Value("${spring.task.execution.thread-name-prefix}")
    private String threadNamePrefix;

    @Bean("myAsync")
    public Executor asyncExecutor(){
        log.info("线程池加载--开始");
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 核心线程池大小
        executor.setCorePoolSize(coreSize);
        // 最大线程数
        executor.setMaxPoolSize(maxSize);
        // 活跃时间
        executor.setKeepAliveSeconds(keepAlive);
        // 队列容量
        executor.setQueueCapacity(queueCapacity);
        // 线程名字前缀,设置前缀 自定义的Bean名称则失效
        executor.setThreadNamePrefix(threadNamePrefix);
        // 主线程等待子线程执行时间
        //executor.setAwaitTerminationSeconds(10);
        executor.initialize();
        log.info("线程池加载--完毕");
        return  executor;
    }

    /**
     * 只能捕获无返回值的异步方法,有返回值的被主线程处理
     * @param
     * @return org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler
     * @throws
     */
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new CustomAsyncExceptionHandler();
    }

    /**
     * @description:  处理异步方法中未捕获的异常
     * @return
     */
    class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
        @Override
        public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
            log.info("Exception message - {}", throwable.getMessage());
            log.info("Method name - {}", method.getName());
            log.info("Parameter values - {}", Arrays.toString(obj));
            if (throwable instanceof Exception) {
                Exception exception = (Exception) throwable;
                log.info("exception:{}", exception.getMessage());
            }
            throwable.printStackTrace();
        }
    }
}

4、单独编写异步任务类

@Component
@Slf4j
public class AsyncTask {

    @Async("myAsync")
    public void sendMsg(){
        log.info("异步发送短信-开始:当前线程={}",Thread.currentThread().getName());
        for (int i=0;i<20;i++){
            try {
                Thread.sleep(1000L);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            log.info("正在发送第{}条短信,线程:{}",i+1,Thread.currentThread().getName());
        }
        log.info("异步发送短信-结束:当前线程={}",Thread.currentThread().getName());
    }
}

5、其他service调用异步任务即可