当前位置: 首页 > 后端技术 > Java

动态调整线程池参数

时间:2023-04-01 23:14:42 Java

goal实现线程池参数动态调整,监控线程池运行实现1.线程池参数可调核心线程数超时时间最大线程数拒绝策略由于队列BlockingQueue是final类型,所以有是没有外部修改条目。但是您可以重写LinkedBlockingQueue并将容量设置为非最终。二是结合配置中心实现动态调整。这里的配置中心使用Apollo来监听配置中心的变化,然后更新线程池配置。示例代码如下:@Slf4j@ComponentpublicclassDynamicThreadPoolConfig{/**线程执行器**/privatevolatileThreadPoolExecutor执行器;/**核心线程数**/privateIntegercorePoolSize=10;/**最大线程数**/privateIntegermaximumPoolSize=20;/**待执行队列的长度**/privateIntegerworkQueueSize=1000;/**线程空闲时间**/privateLongkeepAliveTime=1000L;/**线程名称**/privateStringthreadName;privateConfigconfig=ConfigService.getConfig("项目配置中心命名空间");公共DynamicThreadPoolConfig(){初始化(配置);}/***初始化*/privatevoidinit(Configconfig){log.info("线程池初始化......");if(executor==null){synchronized(DynamicThreadPoolConfig.class){if(executor==null){StringcorePoolSizeProperty=config.getProperty("corePoolSize",corePoolSize.toString());log.info("修改前的核心线程池:{}",core池大小属性);StringmaximumPoolSizeProperty=config.getProperty("maximumPoolSize",maximumPoolSize.toString());StringkeepAliveTImeProperty=config.getProperty("keepAliveTime",keepAliveTime.toString());BlockingQueueworkQueueProperty=newLinkedBlocking(workQueueSize);executor=newThreadPoolExecutor(Integer.valueOf(corePoolSizeProperty),Integer.valueOf(maximumPoolSizeProperty),Long.valueOf(keepAliveTImeProperty),TimeUnit.MILLISECONDS,workQueueProperty);}}}}/***在配置中心监听变化后,更新线程池配置*@paramchangeEvent*/@ApolloConfigChangeListenerpublicvoidonChange(ConfigChangeEventchangeEvent){log.info("线程池参数配置变化,命名空间:{}",changeEvent.getNamespace());对于(字符串键:changeEvent.changedKeys()){ConfigChangechange=changeEvent.getChange(key);StringnewValue=change.getNewValue();刷新线程池(键,新值);}}/***更新线程池配置*@paramkey*@paramnewValue*/privatevoidrefreshThreadPool(Stringkey,StringnewValue){if(executor==null){return;}if(ParamsEnum.CORE_POOL_SIZE.getParam().equals(key)){executor.setCorePoolSize(Integer.valueOf(newValue));log.info("修改核心线程序数key={},value={}",key,newValue);}if(ParamsEnum.MAXIMUM_POOL_SIZE.getParam().equals(key)){executor.setMaximumPoolSize(Integer.valueOf(newValue));log.info("修改最大线路数key={},value={}",key,newValue);}if(ParamsEnum.KEEP_ALIVE_TIME.getParam().equals(key)){executor.setKeepAliveTime(Integer.valueOf(newValue),TimeUnit.MILLISECONDS);log.info("修改线程空闲时间key={},value={}",key,newValue);}}publicThreadPoolExecutorgetExecutor(){返回执行器;}}@AllArgsConstructorpublicenumParamsEnum{CORE_POOL_SIZE("apollo.async.executor.thread.core_pool_size","核心线程数"),MAXIMUM_POOL_SIZE("dynamic.maximumPoolSize","最大线程数"),KEEP_ALIVE_TIME("dynamic.keepAliveTime","线程空闲时间"),;@Getter私有字符串参数;@GetterprivateStringdesc;}第三,通过监控的方式修改线程池的相关参数很重要,但是知道什么时候修改也很重要。可以考虑定时采集,通过日志输出达到临界点后输出告警同样,ThreadPoolExecutor也提供了获取线程池相关信息的API:这里通过定时任务进行统计。需要注意的是EnableScheduling注解@Slf4j@Component@Async@ConditionalOnBean(DynamicThreadExecutor.class)publicclassThreadPoolMonitorSchedule{@AutowiredprivateDynamicThreadExecutordynamicThreadExecutor;@Scheduled(fixedDelay=2000)publicvoidwatchThreadPoolInfo(){log.info("开始统计线程池相关数据");ThreadPoolExecutorthreadPoolExecutor=dynamicThreadExecutor.getExecutor.queue();得到队列();//线程活跃度:当活跃线程数趋于maximumPoolSize时,表示线程负载趋于增加。log.info("核心线程数:{},活跃线程数:{},最大线程数:{},线程池活跃度:{},已完成任务数:{},"+"队列大小:{},当前排队线程数:{},剩余队列大小:{},队列使用:{}”,threadPoolExecutor.getCorePoolSize(),threadPoolExecutor.getActiveCount(),threadPoolExecutor.getMaximumPoolSize(),divide(threadPoolExecutor.getActiveCount(),threadPoolExecutor.getMaximumPoolSize()),threadPoolExecutor.getCompletedTaskCount(),(queue.size()+queue.remainingCapacity()),queue.size(),queue.remainingCapacity(),divide(queue.size(),队列.size()+queue.remainingCapacity()));}privateStringdivide(intnum1,intnum2){returnString.format("%1.2f%%",Double.parseDouble(num1+"")/Double.parseDouble(num2+""));}}/***启动类*/@MapperScan({"com.demo.dao"})@SpringBootApplication@EnableScheduling公共类DemoApplication{publicstaticvoidmain(String[]args){SpringApplication.run(DemoApplication.class,args);}}