线程池优化任务Demo
作者:互联网
背景:
开发中数据库IO和网络IO成本较高,使用线程池进行优化
yml配置:
# 定时任务线程池基础参数
task:
pool:
corePoolSize: 5 # 核心线程数
maxPoolSize: 20 # 设置最大线程数
keepAliveSeconds: 300 # 设置线程活跃时间
queueCapacity: 100 # 设置队列容量
定义参数实体Bean
package com.it.stock.common.domain;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "task.pool")
@Data
public class TaskThreadPoolInfo {
/**
* 核心线程数(获取硬件):线程池创建时候初始化的线程数
*/
private Integer corePoolSize;
private Integer maxPoolSize;
private Integer keepAliveSeconds;
private Integer queueCapacity;
}
配置线程池
package com.it.stock.config;
import com.it.stock.common.domain.TaskThreadPoolInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
@EnableConfigurationProperties(TaskThreadPoolInfo.class)
@Slf4j
public class TaskExecutePool {
private TaskThreadPoolInfo info;
public TaskExecutePool(TaskThreadPoolInfo info) {
this.info = info;
}
/**
* 定义任务执行器
* @return
*/
@Bean(name = "threadPoolTaskExecutor",destroyMethod = "shutdown")
public ThreadPoolTaskExecutor threadPoolTaskExecutor(){
//构建线程池对象
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
//核心线程数:核心线程数(获取硬件):线程池创建时候初始化的线程数
taskExecutor.setCorePoolSize(info.getCorePoolSize());
//最大线程数:只有在缓冲队列满了之后才会申请超过核心线程数的线程
taskExecutor.setMaxPoolSize(info.getMaxPoolSize());
//缓冲队列:用来缓冲执行任务的队列
taskExecutor.setQueueCapacity(info.getQueueCapacity());
//允许线程的空闲时间:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
taskExecutor.setKeepAliveSeconds(info.getKeepAliveSeconds());
//线程名称前缀
taskExecutor.setThreadNamePrefix("StockThread-");
//设置拒绝策略
// taskExecutor.setRejectedExecutionHandler(rejectedExecutionHandler());
//参数初始化
taskExecutor.initialize();
return taskExecutor;
}
}
业务层注入线程池对象
/**
* 注入线程池对象
*/
@Autowired
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
threadPoolTaskExecutor.execute(()->{
//需要多线程执行的内容
}
例:
@Override
public void getStockSectorRtIndex() {
//发送板块数据请求
String result = restTemplate.getForObject(stockInfoConfig.getBlockUrl(), String.class);
//响应结果转板块集合数据
List<StockBlockRtInfo> infos = parserStockInfoUtil.parse4StockBlock(result);
log.info("板块数据量:{}",infos.size());
//数据分片保存到数据库下 行业板块类目大概50个,可每小时查询一次即可
Lists.partition(infos,20).forEach(list->{
threadPoolTaskExecutor.execute(()->{
//20个一组,批量插入
stockBlockRtInfoMapper.insertBatch(list);
});
});
}
线程池工作流程简述:
1-线程池注入后但未执行任务,线程数为0;
2-有任务执行,但任务数小于核心线程数时,则开启任务数个核心线程数,核心线程数未开启完全时,一旦有任务执行,则开启新线程,直至达到核心线程总数;
3-线程执行数达到总核心线程数后,有线程需执行则进入线程队列;
4-线程队列数达到最大值后,如有新线程需执行,则开启新线程直至最大线程数;
5-当总线程数大于最大线程数+线程队列最大长度后,触发任务拒绝策略;
线程池拒绝策略
-
AbortPolicy 总结抛出异常,中断程序执行
-
DiscardPolicy 触发拒绝策略的任务直接丢弃,不抛出异常
-
DiscardOldestPolicy 丢弃存活时长最长的任务
-
CallerRunsPolicy(推荐) 当前线程处理不了,则回调主线程,让主线程处理任务
-
自定义拒绝策略:实现RejectedExecutionHandler接口
标签:info,Demo,private,任务,线程,taskExecutor,import,优化 来源: https://www.cnblogs.com/albert-liu/p/16353403.html