线程池的配置策略

通常情况下,这是一个复杂的活。所以从别人那里百度了几个过来,我只知道第一个

根据任务性质设置

要想合理的配置线程池,就必须首先分析任务特性,可以从以下几个角度来进行分析:

1)任务的性质:CPU密集型任务,IO密集型任务和混合型任务。

2)任务的优先级:高,中和低。

3)任务的执行时间:长,中和短。

4)任务的依赖性:是否依赖其他系统资源,如数据库连接。

任务性质不同的任务可以用不同规模的线程池分开处理。CPU密集型任务配置尽可能小的线程,如配置CPU数+1个线程的线程池。IO密集型任务则由于线程并不是一直在执行任务,则配置尽可能多的线程,如2*CPU数。混合型的任务,如果可以拆分,则将其拆分成一个CPU密集型任务和一个IO密集型任务,只要这两个任务执行的时间相差不是太大,那么分解后执行的吞吐率要高于串行执行的吞吐率,如果这两个任务执行时间相差太大,则没必要进行分解。我们可以通过Runtime.getRuntime().availableProcessors()方法获得当前设备的CPU个数。

执行时间不同的任务可以交给不同规模的线程池来处理,或者也可以使用优先级队列,让执行时间短的任务先执行。

依赖数据库连接池的任务,因为线程提交SQL后需要等待数据库返回结果,如果等待的时间越长CPU空闲时间就越长,那么线程数应该设置越大,这样才能更好的利用CPU。

建议使用有界队列,有界队列能增加系统的稳定性和预警能力,可以根据需要设大一点,比如几千。我在测试一个线程池的时候,使用循环不断提交新的任务,造成任务积压在线程池,最后程序不断的抛出抛弃任务的异常。如果使用无界队列,线程池的队列就会越来越多,有可能会撑满内存,导致整个系统不可用,而不只是后台任务出现问题。

通常这种设置方式是比较粗略的方式。

利特尔法则

利特尔法则(Little’s law)是说,一个系统请求数等于请求的到达率与平均每个单独请求花费的时间之乘积

我们可以使用利特尔法则(Little’s law)来判定线程池大小。我们只需计算请求到达率和请求处理的平均时间。然后,将上述值放到利特尔法则(Little’s law)就可以算出系统平均请求数。若请求数小于我们线程池的大小,就相应地减小线程池的大小。与之相反,如果请求数大于线程池大小,事情就有点复杂了。

当遇到有更多请求待处理的情况时,我们首先需要评估系统是否有足够的能力支持更大的线程池。准确评估的前提是,我们必须评估哪些资源会限制应用程序的扩展能力。在本文中,我们将假定是CPU,而在实际中可能是其它资源。最简单的情况是,我们有足够的空间增加线程池的大小。若没有的话,你不得不考虑其它选项,如软件调优、增加硬件,或者调优并增加硬件。

具体的我们可以参考这篇文章:

http://www.infoq.com/cn/articles/Java-Thread-Pool-Performance-Tuning

配置文件中配置

如果是对系统性能非常重要的一个线程池,与其猜测该线程池的合理大小,不如将它的参数开放出来。因为线程池的合理大小和系统资源也是息息相关的,假设你在设备A上面的线程池大小已经是最优了,不见得把程序放到设备B上面同样是最优的。放在配置文件中,可以方便将来根据系统运行情况进行调整。

我们看看开源任务调度框架Quartz开放了哪些参数:

<bean id="executor"class=“org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor”>

<property name="corePoolSize"value="6" />

<property name="maxPoolSize"value="16" />

<property name="queueCapacity"value="500" />

Quart开放了核心线程数目、最大线程数目、任务队列的容量这三个重要的参数,他们的设置都是和系统资源息息相关的。

线程池的监控

通过线程池提供的参数进行监控。线程池里有一些属性在监控线程池的时候可以使用:

taskCount:线程池需要执行的任务数量。

completedTaskCount:线程池在运行过程中已完成的任务数量。小于或等于taskCount。

largestPoolSize:线程池曾经创建过的最大线程数量。通过这个数据可以知道线程池是否满过。如等于线程池的最大大小,则表示线程池曾经满了。

getPoolSize:线程池的线程数量。如果线程池不销毁的话,池里的线程不会自动销毁,所以这个大小只增不+ getActiveCount:获取活动的线程数。

通过扩展线程池进行监控。通过继承线程池并重写线程池的beforeExecute,afterExecute和terminated方法,我们可以在任务执行前,执行后和线程池关闭前干一些事情。如监控任务的平均执行时间,最大执行时间和最小执行时间等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值