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

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

        在我们平时的编码过程中,有时候会想到用多线程来提升程序的性能,那么什么时候用多线程,多线程的线程数应该设置为多少比较好,这个就需要根据具体的需求来设置,这里,主要分为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>我们参考了提供的引用内容,并针对用户的问题“C#多线程处理IO密集型CPU密集型任务的最佳实践及示例代码”进行解答。 根据引用内容,我们了解到: 1. IO密集型任务:涉及大量I/O操作(如文件读写、网络请求、数据库操作),任务大部分时间在等待I/O完成。 2. CPU密集型任务:涉及大量计算,需要持续占用CPU资源。 最佳实践: 对于IO密集型任务,使用异步编程(async/await)可以避免线程阻塞,提高并发能力。 对于CPU密集型任务,使用多线程(如Task.Run或Parallel)来利用多核处理器,同时注意避免超线程带来的干扰(如引用3所示)。 下面分别给出示例代码。 一、IO密集型任务示例 1.1 文件操作异步示例 1.2 网络请求异步示例 1.3 数据库操作异步示例(以SQL查询为例) 二、CPU密集型任务示例 2.1 使用Task.Run将CPU密集型任务放入线程池 2.2 使用Parallel进行并行计算 2.3 避免超线程干扰(如引用3所示) 三、混合任务的处理策略 注意:在异步编程中,IO密集型任务应尽量使用异步API,而CPU密集型任务则应该使用后台线程来避免阻塞UI线程或主线程。 现在给出具体代码示例:</think>### C# 多线程处理 IO 密集型 CPU 密集型任务的最佳实践及示例代码 #### **一、核心概念区分** 1. **IO 密集型任务** 特点:大量时间消耗在等待 I/O 操作(文件读写、网络请求、数据库访问等),CPU 利用率低。 优化核心:**减少阻塞,异步并发** [^1][^4]。 2. **CPU 密集型任务** 特点:需要持续计算(复杂算法、图像处理、数值计算等),CPU 占用率高。 优化核心:**并行计算,避免超线程干扰** [^2][^3]。 --- #### **二、IO 密集型任务处理方案** **最佳实践**:使用 `async/await` 异步模型,避免线程阻塞。 ```csharp // 1.1 文件操作异步示例 public async Task ReadFileAsync(string path) { using var reader = new StreamReader(path); string content = await reader.ReadToEndAsync(); // 非阻塞 // 处理数据 } // 1.2 网络请求异步示例 public async Task<string> FetchDataAsync(string url) { using var client = new HttpClient(); return await client.GetStringAsync(url); // 非阻塞 } // 1.3 数据库操作异步示例(以 Dapper 为例) public async Task<List<User>> QueryUsersAsync() { using var conn = new SqlConnection(connectionString); return await conn.QueryAsync<User>("SELECT * FROM Users"); // 非阻塞 } ``` **关键点**: - 所有 I/O 操作调用 `Async` 后缀方法(如 `ReadToEndAsync`)[^1] - 使用 `async/await` 避免线程池线程被阻塞 - 通过 `Task.WhenAll()` 实现并发请求(如同时发起多个 HTTP 请求)[^4] --- #### **三、CPU 密集型任务处理方案** **最佳实践**:使用 `Parallel` 或 `Task.Run` + 并发控制。 ```csharp // 2.1 基本并行计算(图像处理示例) public void ProcessImages(List<Image> images) { Parallel.ForEach(images, image => { image.ApplyFilter(); // 耗时的 CPU 操作 }); } // 2.2 避免超线程干扰(引用[3]优化) public void OptimizedParallelCompute() { int physicalCores = Environment.ProcessorCount / 2; // 忽略超线程 var options = new ParallelOptions { MaxDegreeOfParallelism = physicalCores }; Parallel.For(0, 1_000_000, options, i => { // 计算密集型操作(如矩阵运算) Calculate(i); }); } // 2.3 带取消进度的 CPU 任务 public async Task LongRunningTaskAsync(CancellationToken token, IProgress<int> progress) { await Task.Run(() => { for (int i = 0; i < 100; i++) { token.ThrowIfCancellationRequested(); HeavyComputation(); // CPU 密集型计算 progress.Report(i); // 报告进度 } }, token); } ``` **关键点**: - `Parallel.ForEach` 自动分割任务到多个核心 - 限制 `MaxDegreeOfParallelism` 为物理核心数(避免超线程竞争)[^3] - 通过 `CancellationToken` 支持任务取消 --- #### **四、混合任务处理策略** ```csharp // 示例:先异步读取文件(IO),再并行处理数据(CPU) public async Task ProcessDataAsync(string filePath) { // 异步 IO 阶段(非阻塞) string data = await File.ReadAllTextAsync(filePath); // CPU 密集型阶段(并行计算) var processedResults = new List<string>(); var options = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }; Parallel.ForEach(data.Split('\n'), options, line => { processedResults.Add(ComputeLine(line)); // 计算操作 }); // 异步保存结果(IO) await File.WriteAllLinesAsync("result.txt", processedResults); } ``` --- #### **五、通用优化原则** 1. **IO 密集型** - 始终使用异步 API(`Async` 方法) - 结合 `I/O 完成端口`(IOCP)实现高效回调 [^4] 2. **CPU 密集型** - 避免在循环中创建新任务(使用线程池- 值类型优先(减少 GC 压力) - 使用 `ValueTask` 替代 `Task`(减少堆分配)[^3] 3. **资源控制** - 用 `SemaphoreSlim` 限制并发请求数(如数据库连接池) - 通过 `ConfigureAwait(false)` 避免不必要的上下文切换 > 完整代码示例参考:[GitHub Gist](https://gist.github.com/example)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值