ThreadPoolExecutor线程池实战
2023-04-18 14:05:16 时间
ThreadPoolExecutor线程池实战
Demo已开源至Github,threadDemo
1.配置TreadPoolProperty
ThreadPoolTaskExecutor构造方法:
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
为方便全局使用自定义线程池ThreadPoolTaskExecutor,我们建议使用将其初始化所需参数写入到yml/application配置文件中,以达到不入侵源码且改动线程池运行参数的目的。本文将使用 @ConfigurationProperties注解读取yml配置的方式初始化线程池构造方法。如对获取yml有疑问,可以查看我的另一篇文章,专门讲述了如何获取yml里配置的数据。当然如果您用做demo个人练习,也可以使用赋值的方式完成。
文章链接:如何获取yml里的配置数据?
构造方法参数
- corePoolSize:核心线程数,一般取CPU物理核心数,线程默认一直存活
- maximumPoolSize:最大容纳线程数,一般取核心线程数的2倍
- keepAliveTime:非核心线程的闲置超时时间
- unit:keepAliveTime闲置时间单位,一般取秒
- queueCapacity:工作队列长度
- awaitTerminationSeconds:设置此执行程序应该在关闭时阻止的最大秒数
- threadNamePrefix:线程前缀名
- RejectedExecutionHandler:线程池内阻塞队列已满,无法接受任务的拒绝策略
SpringThreadPoolPropertyConfig.class配置类
@ConfigurationProperties(prefix = "threadpool.property")
public class SpringThreadPoolPropertyConfig {
private Integer corePoolSize;
private Integer maxPoolSize;
private Integer keepAliveSeconds;
private Integer queueCapacity;
private Integer awaitTerminationSeconds;
private String threadNamePrefix;
private Boolean waitForTasksToCompleteOnShutdown;
}
application.yml
threadpool:
property:
corePoolSize: 6
maxPoolSize: 12
keepAliveSeconds: 10
queueCapacity: 1000
awaitTerminationSeconds: 0
threadNamePrefix: pool_
waitForTasksToCompleteOnShutdown: true
SpringThreadPoolConfig.class线程池配置类
@Configuration
@EnableAsync
public class SpringThreadPoolConfig {
@Autowired
private SpringThreadPoolPropertyConfig threadPoolConfig;
@Bean("taskExecutor")
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor customizeThreadPoolTaskExecutor = new ThreadPoolTaskExecutor();
customizeThreadPoolTaskExecutor.setCorePoolSize(threadPoolConfig.getCorePoolSize());
customizeThreadPoolTaskExecutor.setMaxPoolSize(threadPoolConfig.getMaxPoolSize());
customizeThreadPoolTaskExecutor.setKeepAliveSeconds(threadPoolConfig.getKeepAliveSeconds());
customizeThreadPoolTaskExecutor.setQueueCapacity(threadPoolConfig.getQueueCapacity());
customizeThreadPoolTaskExecutor.setAwaitTerminationSeconds(threadPoolConfig.getAwaitTerminationSeconds());
customizeThreadPoolTaskExecutor.setThreadNamePrefix(threadPoolConfig.getThreadNamePrefix());
customizeThreadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(threadPoolConfig.getWaitForTasksToCompleteOnShutdown());
customizeThreadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return customizeThreadPoolTaskExecutor;
}
}
配置完成
使用线程池
@Resource(name = "taskExecutor")
@Slf4j
@Service
public class AsyncServiceImpl implements AsyncService {
@Resource(name = "taskExecutor")
private ThreadPoolTaskExecutor taskExecutor;
@Override
public void processingTimeOperation() {
/**
*
* 在此处理耗时操作业务逻辑,
* 如数据量大的插入,只需要在业务层将List等段截取后的List在for循环中传入每一个List调用异步线程即可
*/
try {
log.info("进入异步");
int activeCount = taskExecutor.getActiveCount();
taskExecutor.submit(() -> log.info(String.valueOf(activeCount))).get();
log.debug("当前线程信息:-{}", taskExecutor.getThreadNamePrefix() + taskExecutor.getActiveCount());
log.info("异步体执行完成");
} catch (Exception e) {
e.printStackTrace();
}
}
}
taskExecutor.submit()中执行异步耗时操作,如大批量插入操作,submit()方法可以返回线程执行结果,无返回值的需求可以使用execute()方法。
注意事项:
1.异步操作相关逻辑需要单独在一个接口和实现类中完成。 2.@Async注解要使用在主线程的业务方法中,如果使用在处理耗时操作的逻辑中,会出现主线程完毕,不走子线程异步代码的问题。 具体可以参考上文Github地址中源码 本文涉及到自定义线程池理论知识部分请查看我的另一篇文章: 自定义线程池理论知识部分
相关文章
- 【技术种草】cdn+轻量服务器+hugo=让博客“云原生”一下
- CLB运维&运营最佳实践 ---访问日志大洞察
- vnc方式登陆服务器
- 轻松学排序算法:眼睛直观感受几种常用排序算法
- 十二个经典的大数据项目
- 为什么使用 CDN 内容分发网络?
- 大数据——大数据默认端口号列表
- Weld 1.1.5.Final,JSR-299 的框架
- JavaFX 2012:彻底开源
- 提升as3程序性能的十大要点
- 通过凸面几何学进行独立于边际的在线多类学习
- 利用行动影响的规律性和部分已知的模型进行离线强化学习
- ModelLight:基于模型的交通信号控制的元强化学习
- 浅谈Visual Source Safe项目分支
- 基于先验知识的递归卡尔曼滤波的代理人联合状态和输入估计
- 结合网络结构和非线性恢复来提高声誉评估的性能
- 最佳实践丨云开发CloudBase多环境管理实践
- TimeVAE:用于生成多变量时间序列的变异自动编码器
- 具有线性阈值激活的神经网络:结构和算法
- 内网渗透之横向移动 -- 从域外向域内进行密码喷洒攻击