C# 多线程 Parallel.For 和 For 谁的效率高?那么 Parallel.ForEach 和 ForEach 呢?
还是那句话:十年河东,十年河西,莫欺少年穷。
今天和大家探讨一个问题:Parallel.For 和 For 谁的效率高呢?
从CPU使用方面而言,Parallel.For 属于多线程范畴,可以开辟多个线程使用CPU内核,也就是说可以并行处理程序。For 循环是单线程的,一个线程执行完所有循环。
因此你会认为:多线程的效率肯定高于单线程。但这样认为是错误的!
例如下面程序:
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
sw.Start(); ParallelLoopResult result =
Parallel.For(, , i =>
{
Console.Write(""); });
sw.Stop();
TimeSpan ts2 = sw.Elapsed;
Console.WriteLine("Parallel.For总共花费{0}ms.", ts2.TotalMilliseconds); //
Stopwatch sw_Eq = new Stopwatch();
sw_Eq.Start();
for (int i = ; i < ; i++)
{
Console.Write("");
}
sw_Eq.Stop();
TimeSpan tssw_Eq = sw_Eq.Elapsed;
Console.WriteLine("for总共花费{0}ms.", tssw_Eq.TotalMilliseconds);
Console.ReadKey();
}

额,为什么For 循环要比Parallel.For 效率要高呢?
这是因为循环体内执行的任务开销太小,仅仅是输出一个空字符串而已。微软的文章已经指出任务的开销大小对并行任务的影响。如果任务很小,那么由于并行管理的附加开销(任务分配,调度,同步等成本),可能并行执行并不是优化方案。这也是上述程序For效率高出的原因。
如果在循环体内执行向数据库插入操作,那么Parallel.For 效率就会高出,在此,我们认为每向数据库插入一条记录花费1毫秒时间,将程序修改如下:
class Program
{
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
sw.Start(); ParallelLoopResult result =
Parallel.For(, , i =>
{
Console.Write("");
Thread.Sleep(); });
sw.Stop();
TimeSpan ts2 = sw.Elapsed;
Console.WriteLine("Parallel.For总共花费{0}ms.", ts2.TotalMilliseconds); //
Stopwatch sw_Eq = new Stopwatch();
sw_Eq.Start();
for (int i = ; i < ; i++)
{
Console.Write("");
Thread.Sleep();
}
sw_Eq.Stop();
TimeSpan tssw_Eq = sw_Eq.Elapsed;
Console.WriteLine("for总共花费{0}ms.", tssw_Eq.TotalMilliseconds);
Console.ReadKey();
}
}
}
执行结果大大改变:

相信到此,大家应该明白了吧!也就说For是同步,Parallel.For 是异步执行。当然,我们也可以使用Thread实现异步编程:
代码如下:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("主线程测试开始..");
Thread th = new Thread(ThMethod);
th.Start();
Thread.Sleep();
Console.WriteLine("主线程测试结束..");
Console.ReadLine();
} static void ThMethod()
{
Console.WriteLine("异步执行开始");
for (int i = ; i < ; i++)
{
Console.WriteLine("异步执行" + i.ToString() + "..");
Thread.Sleep();
}
Console.WriteLine("异步执行完成");
}
}
Parallel.ForEach 和 ForEach 与 Parallel.For 和 For 一样,一个是异步执行,开辟多个线程。一个是同步执行,开辟一个线程。因此,效率方面同上,主要看执行的什么任务,在此不作具体说明。
下面写了一些代码,从下面的代码中我们可以看出Parallel.ForEach具体开辟了几个线程,如下:
class Program
{
static void Main(string[] args)
{
int[] intList = new int[] { , , , , , , , , , };
ParallelLoopResult result = Parallel.ForEach(intList, (s,pls,longs) =>
{
Console.WriteLine(longs + " " + s);
pls.Stop();
if (pls.IsStopped)
{
Parallel.Invoke(Gs,Ks);//异步调用多个方法
}
});
Console.ReadKey();
} public static void Gs()
{
Console.WriteLine("异步方法1");
} public static void Ks()
{
Console.WriteLine("异步方法2");
}
}
上述代码中,调用了Stop()方法,我们都知道,如果是同步执行的,调用Stop()后,会立即停止执行,那么程序只会输出索引值为0的结果。而在异步中不是这样的,异步迭代是多线程且没有顺序的。其执行结果如下:
多次执行的结果可能不同。


如上图所示,第一个图开辟了三个线程,执行顺序为 0 2 1,第二个图开辟了两个线程,执行顺序为:1 0
下面的Invoke()方法是异步调用其他的方法,在此不作解释,可参考C# Invoke()
设置开启的线程的个数:
Parallel.ForEach(NameArray,new ParallelOptions{MaxDegreeOfParallelism=3},(item,pls,i)=>
{
});
@陈卧龙的博客
C# 多线程 Parallel.For 和 For 谁的效率高?那么 Parallel.ForEach 和 ForEach 呢?的更多相关文章
- C# 多线程 Parallel.ForEach 和 ForEach 效率问题研究及理解
from:https://blog.csdn.net/li315171406/article/details/78450534 最近要做一个大数据dataTable循环操作,开始发现 运用foreac ...
- 看看Parallel中高度封装的三个方法,Invoke,For和ForEach
说到.net中的并行编程,也许你的第一反应就是Task,确实Task是一个非常灵活的用于并行编程的一个专用类,不可否认越灵活的东西用起来就越 复杂,高度封装的东西用起来很简单,但是缺失了灵活性,这篇我 ...
- R︱并行计算以及提高运算效率的方式(parallel包、clusterExport函数、SupR包简介)
要学的东西太多,无笔记不能学~~ 欢迎关注公众号,一起分享学习笔记,记录每一颗"贝壳"~ --------------------------- 终于开始攻克并行这一块了,有点小兴 ...
- 【关于java多线程和socket通信的一些记录】---高并发/高负载/高可用/重入锁
多线程:提高cpu的使用效率,多线程是指在同一程序中有多个顺序流在执行. 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程. 线程:同一类线 ...
- Java多线程之线程的创建
好久没有更博客了,最近一直在忙工作的事情.现在终于空下来了,这2天会抓紧时间整理多线程和socket,把JavaSE结束掉. 关于多线程,首先会涉及到哪些东西呢?首先要了解线程,为什么要使用线程,线程 ...
- Java 多线程中的任务分解机制-ForkJoinPool,以及CompletableFuture
ForkJoinPool的优势在于,可以充分利用多cpu,多核cpu的优势,把一个任务拆分成多个“小任务”,把多个“小任务”放到多个处理器核心上并行执行:当多个“小任务”执行完成之后,再将这些执行结果 ...
- Python进阶——为什么GIL让多线程变得如此鸡肋?
本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理 做 Python 开发时,想必你肯定听过 GIL,它经常被 Python 程序员吐槽,说 Pytho ...
- 详解JAVA8Stream API {全}
1: 概述 1.1 优势 1.2 与传统迭代器的区分 1.3 流的操作类型分为两种: 2:流的构造与转换 2:1 常见构造 2.2: 三大包装类型的构造 2.3 并行流的规则输出 2.4 流的转换 3 ...
- SQL Server调优系列玩转篇三(利用索引提示(Hint)引导语句最大优化运行)
前言 本篇继续玩转模块的内容,关于索引在SQL Server的位置无须多言,本篇将分析如何利用Hint引导语句充分利用索引进行运行,同样,还是希望扎实掌握前面一系列的内容,才进入本模块的内容分析. 闲 ...
随机推荐
- FreeSSHD login with permission denied
登录遇到问题: Permission denied, please try again. 解决方法: 在window中使用freesshd开启ssh后,客户端登陆时报 access denied错误 ...
- [20170615]执行dbms_sqldiag.dump_trace看执行计划.txt
[20170615]执行dbms_sqldiag.dump_trace看执行计划.txt --//上午在想查看10053执行计划时使用包时出现如下提示: SCOTT@book> @ &r ...
- JMeter—后置处理器(十)
参考<全栈性能测试修炼宝典JMeter实战>第六章 JMeter 元件详解中第五节后置处理器后置处理器是用来处理采样器发送的请求后得到的响应数据 一.Debug PostProcessor ...
- iptable用法
一:添加屏蔽IP #禁止此IP访问服务器iptables -I INPUT -s 1.2.3.4 -j DROP或iptables -A INPUT -s 1.2.3.4 -j DROP#禁止服务器访 ...
- JavaScript高级特性-创建对象的九种方式
1. 对象字面量 通过这种方式创建对象极为简单,将属性名用引号括起来,再将属性名和属性值之间以冒号分隔,各属性名值对之后用逗号隔开,最后一个属性不用逗号隔开,所有的属性名值对用大括号括起来,像这样: ...
- Kibana中的Coordinate Map地图报索引错误的问题
今天做地图定位展示,展示的是ApacheWeb服务器的访问日志文件中的来源IP.但是中间出现了报错环节,说是索引不能匹配到geo_point类型,实在是不懂这是在说什么,后来在网站找了方法就解决了.主 ...
- January 25th, 2018 Week 04th Thursday
What made something precious? Losing it and finding it. 一件东西怎样才会变得珍贵无比?先弄丢了它,然后又找到了. A short time ag ...
- 命令行方式安装Pycharm
sudo apt install snapd snapd-xdg-open snap refresh sudo snap install pycharm-professional --classic
- Mac OS X 下优化 Terminal,一篇就够了!
先上最终效果图: 目录 目录 1. 相关工具介绍 2. 配置总览 3. 安装步骤 3.1. 安装 iTerm2 3.2. 安装XCode's Command line tools 3.3. 检查 zs ...
- github(1)安装及使用图文详解
教程https://blog.csdn.net/qq_32166627/article/details/54427622 下载地址:https://desktop.github.com/