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引导语句充分利用索引进行运行,同样,还是希望扎实掌握前面一系列的内容,才进入本模块的内容分析. 闲 ...
随机推荐
- 腾讯X5WebView集成及在移动端中使用
工作中经常涉及H5网页的加载工作,最多使用的就是安卓系统控件WebView,但是当网页内容比较多的时候,需要等待很久才能加载完,加载完后用户才能看到网页中的内容,这样用户需要等很久,体验很差. 那能不 ...
- 洗礼灵魂,修炼python(54)--爬虫篇—urllib2模块
urllib2 1.简介 urllib2模块定义的函数和类用来获取URL(主要是HTTP的),他提供一些复杂的接口用于处理: 基本认证,重定向,Cookies等.urllib2和urllib差不多,不 ...
- 洗礼灵魂,修炼python(30)--装饰器(2)—>装饰器总结+进阶使用
在上一篇博文的经典案例中,我想你应该对装饰器有很好的了解了,不过光有那些还不够真的,还需要总结和进阶一下,所以本篇博文解析装饰器进阶. 装饰器 1.什么是装饰器? 个人理解:装饰器又叫语法糖,指的是对 ...
- 第七章 鼠标(CHECKER2)
CHECKER2程序包含一个键盘接口,内容与CHECKER1完全相同.利用←.→.↑.↓四个方向键可以在25个矩形之间移动鼠标指针.Home键把鼠标指针移动到左上角的矩形:End键使鼠标指针落到右下角 ...
- 2018. first week now at home
外面雪刚停. 现在是2018.1.5 2018 needs to consider next steps了.未雨绸缪啊 下面是2017年last working day 外面黑了,水面上黑 ...
- Unity3d自制字体
这篇教学中会使用到BMFont 这个工具 准备好Unity5.3.2版本,其他版本会有异常 一.制作字体 下载链接: http://www.angelcode.com/products/bmfont/ ...
- Spring容器技术内幕之内部工作机制
引言 Spring容器就像一台构造精妙的机器,我们通过配置文件向机器传达控制信息,机器就能够按照设定的模式工作.如果将Spring容器比作一辆车,那么可以将BeanFactory看成汽车的发动机,而A ...
- 罗马数字转整数的golang实现
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 字符 数值 I V X L C D M 例如, 罗马数字 2 写做 II ,即为两个并列的 1.12 写做 XII ,即为 X + ...
- [ ArcGIS for Server 10.1 系列 ] - 重新创建Site
一般当ArcGIS Server Site发生错误.ArcGIS Server无法启动或者ArcGIS Server某服务没有实例,就可能需要重新的创建Site.有时可以通过重新创建Site,就发现其 ...
- 深入分析escape()、encodeURI()、encodeURIComponent()的区别及示例
JavaScript中有三个可以对字符串编码的函数,分别是: escape,encodeURI,encodeURIComponent,相应3个解码函数:unescape,decodeURI,decod ...