线程池大小设置,CPU的核心数、线程数的关系和区别,同步与堵塞完全是两码事

线程池应该设置多少线程合适,怎么样估算出来。最近接触到一些相关资料,现作如下总结。

最开始接触线程池的时候,没有想到就仅仅是设置一个线程池的大小居然还有这么多的学问,汗颜啊。

首先,需要考虑到线程池所进行的工作的性质:

  • IO密集型
  • CPU密集型

简单的分析来看,如果是CPU密集型的任务,我们应该设置数目较小的线程数,比如CPU数目加1。如果是IO密集型的任务,则应该设置可能多的线程数,由于IO操作不占用CPU,所以,不能让CPU闲下来。当然,如果线程数目太多,那么线程切换所带来的开销又会对系统的响应时间带来影响。

《linux多线程服务器端编程》中有一个思路,CPU计算和IO的阻抗匹配原则。

如果线程池中的线程在执行任务时,密集计算所占的时间比重为P(0<P<=1),而系统一共有C个CPU,为了让CPU跑满而又不过载,线程池的大小经验公式 T = C / P。在此,T只是一个参考,考虑到P的估计并不是很准确,T的最佳估值可以上下浮动50%。

这个经验公式的原理很简单,T个线程,每个线程占用P的CPU时间,如果刚好占满C个CPU,那么必有 T * P = C。

下面验证一下边界条件的正确性:

假设C = 8,P = 1.0,线程池的任务完全是密集计算,那么T = 8。只要8个活动线程就能让8个CPU饱和,再多也没用了,因为CPU资源已经耗光了。

假设C = 8,P = 0.5,线程池的任务有一半是计算,有一半在等IO上,那么T = 16.考虑操作系统能灵活,合理调度sleeping/writing/running线程,那么大概16个“50%繁忙的线程”能让8个CPU忙个不停。启动更多的线程并不能提高吞吐量,反而因为增加上下文切换的开销而降低性能。

如果P < 0.2,这个公式就不适用了,T可以取一个固定值,比如 5*C。另外公式里的C不一定是CPU总数,可以是“分配给这项任务的CPU数目”,比如在8核机器上分出4个核来做一项任务,那么C=4

文章如何合理设置线程池大小里面提到了一个公式:

最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间 )* CPU数目

比如平均每个线程CPU运行时间为0.5s,而线程等待时间(非CPU运行时间,比如IO)为1.5s,CPU核心数为8,那么根据上面这个公式估算得到:((0.5+1.5)/0.5)*8=32。这个公式进一步转化为:

最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1)* CPU数目

可以得出一个结论:
线程等待时间所占比例越高,需要越多线程。线程CPU时间所占比例越高,需要越少线程。

workQueue:保存任务的阻塞队列,与线程池的大小有关:

当运行的线程数少于corePoolSize时,在有新任务时直接创建新线程来执行任务而无需再进队列

当运行的线程数等于或多于corePoolSize,在有新任务添加时则选加入队列,不直接创建线程

当队列满时,在有新任务时就创建新线程

原文地址:https://www.cnblogs.com/panxuejun/p/10198102.html

时间: 2024-08-12 17:23:34

线程池大小设置,CPU的核心数、线程数的关系和区别,同步与堵塞完全是两码事的相关文章

ThreadPoolExecutor使用和思考(上)-线程池大小设置与BlockingQueue的三种实现区别

工作中多处接触到了ThreadPoolExecutor.趁着现在还算空,学习总结一下. 前记: jdk官方文档(javadoc)是学习的最好,最权威的参考. 文章分上中下.上篇中主要介绍ThreadPoolExecutor接受任务相关的两方面入参的意义和区别,池大小参数corePoolSize和maximumPoolSize,BlockingQueue选型(SynchronousQueue,LinkedBlockingQueue,ArrayBlockingQueue):中篇中主要聊聊与keepA

ThreadPoolExecutor使用和思考-线程池大小设置与BlockingQueue的三种

工作中多处接触到了ThreadPoolExecutor.趁着现在还算空,学习总结一下. 前记: jdk官方文档(javadoc)是学习的最好,最权威的参考. 文章分上中下.上篇中主要介绍ThreadPoolExecutor接受任务相关的两方面入参的意义和区别,池大小参数corePoolSize和maximumPoolSize,BlockingQueue选型(SynchronousQueue,LinkedBlockingQueue,ArrayBlockingQueue):中篇中主要聊聊与keepA

如何合理地估算线程池大小?

本文转自:http://ifeve.com/how-to-calculate-threadpool-size/ 如何合理地估算线程池大小? 这个问题虽然看起来很小,却并不那么容易回答.大家如果有更好的方法欢迎赐教,先来一个天真的估算方法:假设要求一个系统的 TPS(Transaction Per Second或者Task Per Second)至少为20,然后假设每个Transaction由一个线程完成,继续假设平均每个线程处理一个Transaction的时间为4s.那么 问题转化为: 如何设计

如何决定 Web 应用的线程池大小

在部署 web 应用到生产环境,或者在对 web 应用进行性能测试的时候,经常会有人问:如何决定 web 应用线程池大小?决定一个 IO 阻塞型 web 应用的线程池大小是一项很艰巨的任务.通常是通过进行大量的性能测试来完成.在一个 web 应用中同时拥有多个线程池会让决定最优线程池大小的过程变得更加复杂.本文将就这个常见的问题进行一些讨论和建议. 线程池 web 应用中的线程池大小决定了在指定时间内能够处理的并发请求数.如果一个 web 应用接收到的请求数高于线程池大小,多出来的请求将进入队列

如何决定Web应用的线程池大小

线程池(Thread Pool)在Web应用中线程池的大小决定了在任何一个时间点应用可以处理请求的并发数.如果一个系统收到的请求数超过了线程池的大小,那么超出的请求要么进入等待队列要么被拒绝.请注意,并发和并行是不同的.并发请求是指在任何一个时间点,所有被处理的请求中只有只有很少一部分占用CPU(译者注:轮流使用CPU).并行是指在任何一个时间点,所有被处理的请求同时在CPU上运行.在非阻塞式(NO-Blocking)应用中(如NodeJs),一个单独的线程或进程可以并发处理多个请求.而在多核C

如何设置tomcat线程池大小?

背景 在我们的日常开发中都涉及到使用tomcat做为服务器,但是我们该设置多大的线程池呢?以及根据什么原则来设计这个线程池呢?接下来,我将介绍本人是怎么设计以及计算的. 目标 确定tomcat服务器线程池大小 具体方法 众所周知,tomcat接受一个request后处理过程中,会设计到cpu的时间和IO等待的时间.其中IO等待时,cpu被动放弃执行,其他线程就可以利用这段时间片进行操作. 所以我们可以采用服务器IO优化的通用规则: 线程大小 = ( (线程io时间 + 线程cpu)  / 线程c

设置线程池大小 &middot; 贰白

线程池大小多少合适? 概述 通常来说,服务分为两种类型: CPU密集型 也叫计算密集型,当计算机完成任务的时间主要取决于CPU的速度时,计算机受CPU限制(或计算限制):CPU利用率很高,可能在100%的使用时间内持续很多秒或分钟.外围设备产生的中断可能会被缓慢处理或无限期延迟处理. IO密集型 完成计算所花费的时间主要由等待I/O操作完成所花费的时间来确定. 这与CPU密集的任务相反. 当请求数据的速率低于其消耗速率时,或者换句话说,请求数据所花费的时间多于处理数据所花费的时间,就会出现这种情

ThreadPoolExecutor线程池参数设置技巧

一.ThreadPoolExecutor的重要参数   corePoolSize:核心线程数 核心线程会一直存活,及时没有任务需要执行 当线程数小于核心线程数时,即使有线程空闲,线程池也会优先创建新线程处理 设置allowCoreThreadTimeout=true(默认false)时,核心线程会超时关闭 queueCapacity:任务队列容量(阻塞队列) 当核心线程数达到最大时,新任务会放在队列中排队等待执行 maxPoolSize:最大线程数 当线程数>=corePoolSize,且任务队

ThreadPoolExecutor线程池参数设置技巧(转)

一.ThreadPoolExecutor的重要参数   corePoolSize:核心线程数 核心线程会一直存活,及时没有任务需要执行 当线程数小于核心线程数时,即使有线程空闲,线程池也会优先创建新线程处理 设置allowCoreThreadTimeout=true(默认false)时,核心线程会超时关闭 queueCapacity:任务队列容量(阻塞队列) 当核心线程数达到最大时,新任务会放在队列中排队等待执行 maxPoolSize:最大线程数 当线程数>=corePoolSize,且任务队