线程池在springboot中简单使用

本文介绍如何利用Spring框架的线程池功能实现异步发送多封邮件。通过配置ThreadPoolTaskExecutor来创建一个基于线程池的任务执行器,再结合@EnableAsync和@Async注解启用和标记异步方法,有效地提高了邮件发送效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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";
    }

}

--运行结果

--

### Spring Boot 中线程池使用教程 #### 配置线程池 为了在Spring Boot中高效地管理和利用多线程,可以通过配置文件或Java代码来设置线程池的相关属性。通常情况下,推荐的方式是在`application.properties`或`application.yml`文件内指定这些参数[^1]。 例如,在YAML格式下: ```yaml spring: task: execution: pool: core-size: 5 max-size: 10 queue-capacity: 100 ``` 上述配置创建了一个核心大小为5的最大容量可达10的工作队列,其等待任务的数量上限设定为100项。 如果需要更灵活地控制线程池的行为,则可以在项目里编写一个实现了`AsyncConfigurer`接口并重写了其中方法的类来进行定制化的初始化工作;或者是直接声明一个新的`ThreadPoolTaskExecutor` Bean对象用于覆盖默认行为[^3]。 ```java import org.springframework.context.annotation.Bean; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; public class AsyncConfig { @Bean(name = "customExecutor") public ThreadPoolTaskExecutor threadPoolTaskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(7); executor.setMaxPoolSize(42); executor.setQueueCapacity(11); executor.initialize(); return executor; } } ``` 这段代码展示了如何定义名为`customExecutor`的异步执行器bean,并设置了不同的初始值给它所关联的任务调度者实例。 #### 提交任务到线程池 一旦完成了线程池的基础构建之后,就可以向里面提交待处理的任务了。这一步骤主要依赖于`@EnableAsync`注解开启全局异步支持功能以及`@Async`标记具体的方法使之成为可被后台运行的目标函数[^2]。 下面是一个简单的例子说明怎样让某个服务中的业务逻辑能够异步执行: ```java import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @Service public class MyService { @Async("customExecutor") // 指定使用线程池名称 public void doSomethingAsynchronously(String param) throws InterruptedException { System.out.println(Thread.currentThread().getName()+" is processing "+param); Thread.sleep(5000); // Simulate long-running process. System.out.println(param+" has been processed."); } } ``` 在这个案例当中,当调用了`doSomethingAsynchronously()`这个带有`@Async`修饰符的服务层方法后,实际的操作将会由之前提到过的那个叫作`customExecutor`的线程池负责完成,而不会阻塞当前主线程继续往下走。 #### 监控与管理 最后但同样重要的是要考虑到对正在运作着的线程池状态实施有效的监督措施。借助像Micrometer这样的库可以帮助收集有关性能指标的数据以便后续分析之用。另外还可以考虑集成Prometheus、Grafana之类的开源平台实现更加直观可视化的效果展示。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值