SpringBoot自定义线程池

使用SpringBoot构建应用时,如何使用线程处理异步任务?其实springBoot已经提供了默认的实现,通过在启动类上加上注解@EnableAsync, 然后在需要异步处理的方法上增加注解@Async即可启动一个线程进行异步处理。其实质类似于:new Thread(()-{System.out.print("处理异步任务")}).start()。但需要注意的是@Async默认使用的是SimpleAsyncTaskExecutor,每次提交任务都创建线程,要小心在使用大任务的场景下创建大量线程导致OOM异常。所以,还是自定义线程池好。自定义线程池有2种实现方式。

1. 自定义线程池,然后使用自己定义的线程池

  1.1 修改application.yml文件,增加线程池的配置参数,如下

   

 

 

 1.2 线程池配置属性类MyThreadPoolConfig .java

复制代码
/**
* 线程池配置属性类
*/

@ConfigurationProperties(prefix = "mytask.pool")

public class MyThreadPoolConfig {
private int corePoolSize;

private int maxPoolSize;

private int keepAliveSeconds;

private int queueCapacity;

}
复制代码

 

1.3  启动类上一定要开启线程异步支持:@EnableAsync

复制代码
@EnableAsync
@EnableConfigurationProperties({MyThreadPoolConfig.class})
@SpringCloudApplication

public class application
{
public static void main(String[] args)
{
SpringApplication.run(application.class, args);
}
}
复制代码

 

1.4 创建自己的线程池

      

复制代码
/**
 * 创建线程池
 */
@Configuration
public class MyTaskExecutePool {
 
    @Autowired
    private MyThreadPoolConfig config;
 
    @Bean("myTaskPool")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //核心线程池大小
        executor.setCorePoolSize(config.getCorePoolSize());
        //最大线程数
        executor.setMaxPoolSize(config.getMaxPoolSize());
        //队列容量
        executor.setQueueCapacity(config.getQueueCapacity());
        //活跃时间
        executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
        //线程名字前缀
        executor.setThreadNamePrefix("TaskExecutePool-");
 
        // setRejectedExecutionHandler:当pool已经达到maxSize的时候,如何处理新进任务
        // CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
         // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.initialize();
        return executor;
    }
}
复制代码

 

  需要注意的是这样定义的线程池在使用的时候要在@Async主键里指定名称,如:@Async("mytaskExecutor"), 否则会使用spingtBoot提供的默认线程池。

2. 重新spring默认的线程池

  第一种方式创建的线程池在使用的时候必须要指明异步任务要使用的线程池名称,而重新srping默认的线程池,则不需要指定名称,直接写@Asyncj即可。

  配置方式和方式一类似,唯一的区别在于配置类要实现AsyncConfigurer

  

复制代码
/**
* 重新SpringBoot默认的线程池
*/
@Configuration
public class OverrideAsyncTaskExecutePool implements AsyncConfigurer{


//注入配置类
@Autowired
MyThreadPoolConfig config;

@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//核心线程池大小
executor.setCorePoolSize(config.getCorePoolSize());
//最大线程数
executor.setMaxPoolSize(config.getMaxPoolSize());
//队列容量
executor.setQueueCapacity(config.getQueueCapacity());
//活跃时间
executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
//线程名字前缀
executor.setThreadNamePrefix("MyExecutor-");

// setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务
// CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
复制代码

 

posted on   Msea  阅读(2956)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示