线程池 allowCoreThreadTimeOut 小知识

本文深入探讨了线程池中allowCoreThreadTimeOut参数的作用,详细解析了其如何影响核心线程的回收机制,尤其是在定时任务场景下,避免了线程过度占用资源,对提高系统效率和资源利用率有重要意义。

关于线程池:allowCoreThreadTimeOut(true) 的小知识点

1.背景

   检查别人程序发现堆内存2G,但是常驻内存res到3.2G了,经过一系列操作发现线程特别多(1000+), 当然有重复创建线程池的问题。除此之外,由于是数据域应用,为了加速查询,会定时把数据库数据load到缓存,还不部分是应付也个页面N次(20+)查询,希望能支持稍微高一点的并发响应。所以连接池各方面设置比较大。(线程会持续吃RES内存,不释放,默认1M)

2.操作

	期望线程数减少,定时任务用了线程线程之后,能回收掉等等操作。allowCoreThreadTimeOut 支持回收核心线程,合适定时任务这种回收、其他操作就不介绍了,这里仅回顾下它的回收过程。

3.基本介绍

	代码是:
ThreadPoolExecutor#allowCoreThreadTimeOut(true)
	进去是:
 public void allowCoreThreadTimeOut(boolean value) {
        if (value && keepAliveTime <= 0)
            throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
        if (value != allowCoreThreadTimeOut) {
            allowCoreThreadTimeOut = value;
            if (value)
                // 中断空闲线程,第一次设置调用
                // workers 还是空的,不太明白作用
                // 因为这个方法是独立,猜测场景是
                // 某任务过程条件下,手动调用该方法一次
                // 比如shutDown 就是一种条件
                interruptIdleWorkers();
        }
    }
   前面都是声明一些东西,还是找到runWorker 执行的地方:
 final void runWorker(Worker w) {
 		// 一顿操作略
 		// 这里task 获取不到就会跳出循环 @A
 	  while (task != null || (task = getTask()) != null) {
 	  }
 	  // .. 最后会让线程退出
 	  finally {
            processWorkerExit(w, completedAbruptly);
        }
 	  // 操作略
 	  
 }

processWorkerExit 代码:

      try {
            completedTaskCount += w.completedTasks;
            workers.remove(w);
        } finally {
            mainLock.unlock();
        }

从新回去看@A 里面的getTask

 private Runnable getTask() {
        boolean timedOut = false; 
        for (;;) {
            // 一顿操作 省略
            try {
                   // 这里就用到 allowCoreThreadTimeOut 来判断这个值
                   boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
                   
                 // 这个值又会作为 poll 还是 take 的条件  
                 // 由于timed=true,所以我们会用poll
                 // 然后超过 keepAliveTime 没有活动线程,那么就会返回空,从而触发@A 部分跳出循环,回收线程
                Runnable r = timed ?
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take();
                if (r != null)
                    return r;
                timedOut = true;
            } catch (InterruptedException retry) {
                timedOut = false;
            }
        }
    }

那么如果 allowCoreThreadTimeOut=false
没超过核心线程数的情况下、或者异常、中断等情况下
就会进入 workQueue.take() 阻塞等待,那么刚才执行已经执行过任务的那部分核心线程就不会被回收了。

小结:

  1.虽然线程池用了很久,从1.6 到1.8 都看了下源码,但是还是有些场景和知识点遗忘的地方,仅作为学习记录,加深下印象。
  2.关于线程池的应用很多,从低延迟高并发触发,从IO/CPU 出发,从定时任务量、机器资源排队情况等,需要结合经验、压测,以及合理的业务、线程池拆分找到合适的选择
<think>好的,我现在需要帮助用户在SpringBoot项目中实现动态刷新配置以扩容线程池。首先,我得回忆一下之前学过的相关知识,以及用户提供的引用内容。用户提到了使用Nacos实现动态线程池,还有@Async注解和线程池的扩展。用户的需求是动态调整线程池大小,比如核心线程数、最大线程数等,而无需重启应用。首先,我需要确定SpringBoot中如何配置线程池。通常,我们会使用ThreadPoolTaskExecutor,并通过@Configuration来定义Bean。用户可能已经有一个这样的配置,但现在需要让它能够动态刷新。根据引用2,动态线程池的优势在于应对请求量的波动,而Nacos可以作为配置中心来存储最新的线程池参数。接下来,动态刷新的机制。SpringCloud的@RefreshScope注解可以实现配置的实时刷新,但需要结合配置服务器,比如Nacos。用户需要将线程池的参数(如corePoolSize、maxPoolSize)放在Nacos的配置文件中,然后在SpringBoot应用中监听配置变化,并更新线程池的相应属性。然后,线程池参数的动态调整。即使配置更新了,如何让正在运行的线程池应用这些新值呢?ThreadPoolTaskExecutor本身可能不会自动更新,所以需要手动获取Bean并调用方法来修改参数。比如,可以通过调用setCorePoolSize和setMaxPoolSize方法,但需要注意这些方法是否真的能动态生效。例如,核心线程数可能需要先允许核心线程超时,才能减少数量。另外,用户可能需要扩展ThreadPoolTaskExecutor,像引用3提到的,创建子类来监控线程池状态。这样在调整参数时,可以记录日志或监控变化情况。可能的步骤包括:1.使用Nacos作为配置中心,存储线程池的配置。2.在SpringBoot中通过@Value注入这些配置,并加上@RefreshScope。3.创建ThreadPoolTaskExecutor的Bean,并在初始化时使用配置参数。4.监听配置变更事件,当配置更新时,调用线程池的方法调整参数。5.处理线程池参数动态调整的限制,比如需要设置allowCoreThreadTimeOut为true才能缩减核心线程数。还需要考虑线程池的动态调整是否安全,比如在运行时修改参数是否会导致资源竞争或任务执行异常。可能需要添加一些同步机制,或者确保在修改参数时不会影响正在执行的任务。用户可能遇到的问题包括配置不生效,或者线程池参数调整后没有立即应用。这时候需要检查@RefreshScope是否生效,配置是否正确加载,以及线程池的Bean是否被正确注入和更新。总结下来,解决方案的大致流程是:配置中心管理参数-> SpringBoot应用监听变化->更新线程池Bean的参数->验证调整后的效果。同时,可能需要自定义线程池的监控和日志,以便跟踪调整情况。</think>在Spring Boot中实现动态刷新线程池配置并扩容,可以通过以下步骤实现: ### 一、核心实现方案 1. **配置中心集成** 使用Nacos作为配置中心存储线程池参数,例如: ```yaml thread-pool: core-size: 5 max-size: 10 queue-capacity: 100 ``` 通过`@NacosValue`或`@ConfigurationProperties`注入配置[^2]。 2. **动态线程池初始化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值