多线程使用:线程数的设置--CPU密集型和IO密集型

本文主要探讨多线程在不同场景的应用及线程数设置。介绍了CPU密集型任务消耗大量CPU资源,不适合多线程;IO密集型任务CPU利用率低,适合多线程。还针对不同并发和任务执行时间的业务,给出了线程池线程数的设置建议,并发高业务长的任务需考虑整体架构设计。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        在我们平时的编码过程中,有时候会想到用多线程来提升程序的性能,那么什么时候用多线程,多线程的线程数应该设置为多少比较好,这个就需要根据具体的需求来设置,这里,主要分为CPU密集型和IO密集型的任务。先来介绍以下概念

 

CPU密集型

       CPU密集型会消耗掉大量的CPU资源,例如需要大量的计算,一些复杂运算,逻辑处理之类的。这个时候CPU就卯足了劲在运行,这个时候切换线程,反而浪费了切换的时间,效率不高。

       就像你的大脑是CPU,你本来就在一本心思地写作业,多线程这时候就是要你写会作业,然后立刻敲一会代码,然后在P个图,然后在看个视频,然后再切换回作业。emmmm,过程中你还需要切换(收起来作业,拿出电脑,打开VS…)那你的作业怕是要写到挂科。。。这个时候不太适合使用多线程,你就该一门心思地写作业~

IO密集型

    涉及到网络、磁盘IO的都是IO密集型,这个时候CPU利用率并不高,这个时候适合使用多线程。

    同样以你的大脑为例,IO密集型就是“不烧脑”的工作。例如你需要陪小姐姐或者小哥哥聊天,还需要下载一个VS,还需要看我(黑哥)的博客。这个时候如果使用多线程的话会怎么做?

     咦?小哥哥(小姐姐)给你发消息了,回一下TA,然后呢?TA给你回消息肯定需要时间,这个时候你就可以搜索VS的网站,先下安装包,然后一看,哎呦,TA还没给你回消息,然后看会你黑哥的博客。小哥哥(小姐姐)终于回你了,你回一下TA,接着看我的博客,这就是类似于IO密集型。你可以在不同的“不烧脑”的工作之间切换,来达到更高的效率。而不是小姐姐不回我的信息,我就干等,啥都不干,就等,这个效率可想而知,也许,小姐姐(小哥哥)根本就不会回复你~

多线程的使用和线程数的设置

      开发中我们经常会使用到线程池来处理一些业务,而在不新增设备的情况下,我们所能使用的线程资源又不是无线的,那么高并发、任务执行时间短的业务怎样使用线程池?还有并发不高、任务执行时间长的业务怎样使用线程池?并发高、业务执行时间长的业务怎样使用线程池?

接下来我们进行一一分析:

1:高并发、任务执行时间短的业务,CPU密集型的,线程池线程数可以设置为CPU核数+1,减少线程上下文的切换

2:并发不高、任务执行时间长的业务这就需要区分开看了:

a)假如是业务时间长集中在IO操作上,也就是IO密集型的任务,因为IO操作并不占用CPU,所以不要让所有的CPU闲下来,可以适当加大线程池中的线程数目,让CPU处理更多的业务

b)假如是业务时间长集中在计算操作上,也就是计算密集型任务,这个就没办法了,和(1)一样吧,线程池中的线程数设置得少一些,减少线程上下文的切换

(其实从一二可以看出无论并发高不高,对于业务中是否是cou密集还是I/O密集的判断都是需要的当前前提是你需要优化性能的前提下)

3:并发高、业务执行时间长,解决这种类型任务的关键不在于线程池而在于整体架构的设计,可以引入三方中间件进行异步操作。
 

<think>好的,我现在需要帮用户解决关于线程池参数配置的问题,具体是CPU核心数4,IO密集型任务时,如何设置核心线程数最大线程数。首先,我得回忆一下IO密集型任务的特点。IO密集型任务大部分时间花在输入输出操作上,比如网络请求、文件读写等,这时候线程会阻塞,等待IO完成,所以CPU会有空闲时间。这种情况下,可以适当增加线程数,以便在等待IO时,其他线程可以继续工作,提高CPU利用率。 根据用户提供的引用资料,特别是引用[4]中的公式:线程数 ≈ 1/(1 - x) * coreNum,其中x是IO耗时占比。不过用户可能没有给出具体的x值,这时候可能需要一个通用的方法。比如,引用[2]中提到IO密集型任务通常建议设置为2*CPU核心数,但引用[4]的例子中,当x=0.77时,计算得到约34线程。不过这可能是个极端情况,实际中可能需要更通用的指导。 另外,引用[5]提到使用Runtime.getRuntime().availableProcessors()来动态获取CPU核心数,这里用户给出的是4核,所以需要考虑动态获取而非硬编码。对于IO密集型任务,常见的建议是核心线程数设置CPU核心数+1或者直接2倍,但根据不同的阻塞比例,可能需要更多。最大线程数通常可以设置得更高,比如核心数的几倍,但需要避免过度切换上下文。 还要注意工作队列的选择,比如使用LinkedBlockingQueue,这样当线程数达到核心数时,任务会进入队列,队列满了才会创建新线程。或者可能使用有界队列,但需要处理拒绝策略。用户可能需要具体的数值建议,比如核心线程数设置为4或更高,最大线程数可能是核心数的2倍或根据公式计算。 需要综合引用中的不同观点,给出合理的设置建议,可能分情况讨论,比如没有具体x值时,通用的做法,以及有x值时如何计算。同时需要提到动态调整监控的重要性,避免教条式的设置。</think>### 根据CPU核心数任务类型(IO密集型设置线程池参数的步骤 #### 1. **核心参数定义** - **CPU核心数**:4核(需通过`Runtime.getRuntime().availableProcessors()`动态获取[^5]) - **任务类型**:IO密集型(如网络请求、文件读写等,线程存在大量阻塞等待时间) #### 2. **通用设置原则** - **核心线程数**:建议设置CPU核心数的1-2倍(即4-8),以充分利用CPU空闲时间[^2] - **最大线程数**:根据IO耗时比例动态计算,公式为: $$ \text{线程数} \approx \frac{1}{1 - x} \times \text{CPU核心数} $$ 其中$x$为单个任务中IO操作的耗时占比[^4] #### 3. **具体配置建议** **情况1:无具体IO耗时占比时(通用场景)** - 核心线程数:4(与CPU核心数一致) - 最大线程数:4 × 2 = 8(保守策略) 或 4 × 4 = 16(激进策略) - **理由**:IO密集型任务需更多线程填补阻塞时间,但需避免过多线程导致上下文切换开销[^2] **情况2:已知IO耗时占比时(精确计算)** 假设IO耗时占比$x=0.8$(即80%时间在等待IO): $$ \text{最大线程数} \approx \frac{1}{1 - 0.8} \times 4 = 20 $$ 此时建议: - 核心线程数:4 - 最大线程数:20 #### 4. **辅助配置建议** - **队列类型**:使用`LinkedBlockingQueue`(无界队列)存放待处理任务[^1] - **空闲线程存活时间**:设置较短时间(如30秒),避免资源浪费[^1] - **拒绝策略**:根据业务需求选择`CallerRunsPolicy`或自定义策略 #### 5. **验证与调优** - **监控指标**:观察CPU利用率(建议60%-80%)、线程阻塞率、任务堆积量 - **动态调整**:根据实际负载逐步增加最大线程数,直到性能不再显著提升 --- ### 配置示例(Java代码) ```java int corePoolSize = Runtime.getRuntime().availableProcessors(); // 4 int maxPoolSize = (int)(corePoolSize / (1 - 0.8)); // 假设x=0.8 ThreadPoolExecutor executor = new ThreadPoolExecutor( corePoolSize, maxPoolSize, 30, // 空闲线程存活时间(秒) TimeUnit.SECONDS, new LinkedBlockingQueue<>(), Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy() ); ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值