还是那句话:十年河东,十年河西,莫欺少年穷。

今天和大家探讨一个问题: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 呢?的更多相关文章

  1. C# 多线程 Parallel.ForEach 和 ForEach 效率问题研究及理解

    from:https://blog.csdn.net/li315171406/article/details/78450534 最近要做一个大数据dataTable循环操作,开始发现 运用foreac ...

  2. 看看Parallel中高度封装的三个方法,Invoke,For和ForEach

    说到.net中的并行编程,也许你的第一反应就是Task,确实Task是一个非常灵活的用于并行编程的一个专用类,不可否认越灵活的东西用起来就越 复杂,高度封装的东西用起来很简单,但是缺失了灵活性,这篇我 ...

  3. R︱并行计算以及提高运算效率的方式(parallel包、clusterExport函数、SupR包简介)

    要学的东西太多,无笔记不能学~~ 欢迎关注公众号,一起分享学习笔记,记录每一颗"贝壳"~ --------------------------- 终于开始攻克并行这一块了,有点小兴 ...

  4. 【关于java多线程和socket通信的一些记录】---高并发/高负载/高可用/重入锁

    多线程:提高cpu的使用效率,多线程是指在同一程序中有多个顺序流在执行. 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程. 线程:同一类线 ...

  5. Java多线程之线程的创建

    好久没有更博客了,最近一直在忙工作的事情.现在终于空下来了,这2天会抓紧时间整理多线程和socket,把JavaSE结束掉. 关于多线程,首先会涉及到哪些东西呢?首先要了解线程,为什么要使用线程,线程 ...

  6. Java 多线程中的任务分解机制-ForkJoinPool,以及CompletableFuture

    ForkJoinPool的优势在于,可以充分利用多cpu,多核cpu的优势,把一个任务拆分成多个“小任务”,把多个“小任务”放到多个处理器核心上并行执行:当多个“小任务”执行完成之后,再将这些执行结果 ...

  7. Python进阶——为什么GIL让多线程变得如此鸡肋?

    本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理 做 Python 开发时,想必你肯定听过 GIL,它经常被 Python 程序员吐槽,说 Pytho ...

  8. 详解JAVA8Stream API {全}

    1: 概述 1.1 优势 1.2 与传统迭代器的区分 1.3 流的操作类型分为两种: 2:流的构造与转换 2:1 常见构造 2.2: 三大包装类型的构造 2.3 并行流的规则输出 2.4 流的转换 3 ...

  9. SQL Server调优系列玩转篇三(利用索引提示(Hint)引导语句最大优化运行)

    前言 本篇继续玩转模块的内容,关于索引在SQL Server的位置无须多言,本篇将分析如何利用Hint引导语句充分利用索引进行运行,同样,还是希望扎实掌握前面一系列的内容,才进入本模块的内容分析. 闲 ...

随机推荐

  1. recovery 升级过程执行自定义shell命令

    有时候我们需要,在升级的过程中,执行一些shell命令,来完成我们的一些需求,利用升级过程,进行一些特殊化的操作,思路如下: 第一: 把我们需要执行的命令,写成一个test.sh脚本,然后在recov ...

  2. maven(四):一个基本maven项目的pom.xml配置

    继续之前创建的test项目,一个基本项目的pom.xml文件,通常至少有三个部分 第一部分,项目坐标,信息描述等 <modelVersion>4.0.0</modelVersion& ...

  3. [20171113]修改表结构删除列相关问题4.txt

    [20171113]修改表结构删除列相关问题4.txt --//连续写了3篇修改表结构删除列的相关问题,链接如下: http://blog.itpub.net/267265/viewspace-214 ...

  4. JAVA开发学习

    一.安装JAVA开发工具IDEA,下载Ultimate旗舰版版本,Community社区版不支持Java EE开发...... 下载地址:https://www.jetbrains.com/idea/ ...

  5. scp 实现远程异地备份

    1.先做好脚本 2.再使用crontab 定时执行计划任务 0 1 * * * /usr/bin/expect /root/script/scpautodown.sh  #执行,也可先定义环境变量 0 ...

  6. windows10不能获取有效IP的问题

    最近我的windows10系统一直不能有效获取IP地址(无论有线还是无线),但手工设置IP后又能正常上网,所以怀疑是某个服务未启动的原因. 查了一下百度,发现还真是,现将解决方案记录如下: 1.打开系 ...

  7. python----运算符、布尔值

    一.运算符: + - * / ** // % 1,.   in ,not in 用法(判断某个东西是否在某个东西里面) name = '郑建文' 其中‘郑建文’是字符串, ‘郑’或‘建’或‘文’是一个 ...

  8. 3.1Python数据处理篇之Numpy系列(一)---ndarray对象的属性与numpy的数据类型

    目录 目录 (一)简单的数组创建 1.numpy的介绍: 2.numpy的数组对象ndarray: 3.np.array(list/tuple)创建数组: (二)ndarray对象的属性 1.五个常用 ...

  9. C++基础算法学习——猜假币

    有12枚硬币.其中有11枚真币和1枚假币.假币和真币重量不同,但不知道假币比真币轻还是重.现在,用一架天平称了这些币三次,告诉你称的结果,请你找出假币并且确定假币是轻是重(数据保证一定能找出来).例题 ...

  10. 17秋 软件工程 团队第五次作业 Alpha Scrum3

    17秋 软件工程 团队第五次作业 Alpha Scrum3 今日完成的任务 杰麟:java后端学习: 世强:Android的部门基础信息模块的信息显示和对接后台: 港晨:后台管理登陆界面ui设计: 树 ...