一次性发多封邮件是一个比较耗时的功能,因此可以考虑借助于线程池

Spring通过任务执行器(TaskExecutor)来实现多线程和并发编程。使用ThreadPoolTaskExecutor可实现一个基于线程池的TaskExecutor.在开发中实现异步任务,我们可以在配置类中添加@EnableAsync开始对异步任务的支持,并在相应的方法中使用@Async注解来声明一个异步任务。

1.在application中配置线程

async:
  executor:
    thread:
      core_pool_size: 5
      max_pool_size: 5
      queue_capacity: 99999
      name:
        prefix: async-service-

2.配置

@Configuration
@EnableAsync
public class ExecutorConfig {
    private static final Logger logger = LoggerFactory.getLogger(ExecutorConfig.class);
    @Value("${async.executor.thread.core_pool_size}")
    private int corePoolSize;
    @Value("${async.executor.thread.max_pool_size}")
    private int maxPoolSize;
    @Value("${async.executor.thread.queue_capacity}")
    private int queueCapacity;
    @Value("${async.executor.thread.name.prefix}")
    private String namePrefix;

    @Bean(name = "asyncServiceExecutor")
    public Executor asyncServiceExecutor() {
        logger.info("start asyncServiceExecutor");

        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //配置核心线程数
        executor.setCorePoolSize(corePoolSize);
        //配置最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        //配置队列大小
        executor.setQueueCapacity(queueCapacity);
        //配置线程池中的线程的名称前缀
        executor.setThreadNamePrefix(namePrefix);
        // rejection-policy:当pool已经达到max size的时候,如何处理新任务
        // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //执行初始化
        executor.initialize();
        return executor;
    }
        
}

添加配置的时候也可以直接implements AsyncConfigurer,然后Override getAsyncExecutor()方法

@Override
    public Executor getAsyncExecutor() {
        logger.info("start asyncServiceExecutor");

        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //配置核心线程数
        executor.setCorePoolSize(corePoolSize);
        //配置最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        //配置队列大小
        executor.setQueueCapacity(queueCapacity);
        //配置线程池中的线程的名称前缀
        executor.setThreadNamePrefix(namePrefix);
        // rejection-policy:当pool已经达到max size的时候,如何处理新任务
        // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //执行初始化
        executor.initialize();
        return executor;
    }

 

--

public interface AsyncService {
    /**
     * 执行异步任务
     * 可以根据需求,自己加参数拟定,我这里就做个测试演示
     */
    void executeAsync();
}

--

@Service
public class AsyncServiceImpl implements AsyncService {
    @Autowired
    private SpringMailUtil springMailUtil;
    private static final Logger logger = LoggerFactory.getLogger(AsyncServiceImpl.class);

    @Override
    @Async("asyncServiceExecutor")
    public void executeAsync() {
        logger.info("start executeAsync");
        System.out.println("异步线程要做的事情");
        try {
            String[] receivers = {"m18915228146@163.com"};
            String[] ccs = {"1617950759@qq.com"};
            String title = "test";
            String content = "hello";
            springMailUtil.sendMailByText(receivers,ccs,title,content);

        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("可以在这里执行批量插入等耗时的事情");
        logger.info("end executeAsync");


    }
}

--

@RestController
public class AsyncTestController {
    private static Logger logger = LoggerFactory.getLogger(AsyncTestController.class);
    @Autowired
    private AsyncService asyncService;

    @GetMapping("/asynctest")
    public String async(){
        logger.info("主线程开始");
        for (int i = 0; i < 5; i++) {
            asyncService.executeAsync();

        }
        logger.info("主线程结束");
        return "success";
    }

}

--运行结果

--