from:https://blog.csdn.net/li315171406/article/details/78450534

最近要做一个大数据dataTable循环操作,开始发现 运用foreach,进行大数据循环,并做了一些逻辑处理。在循环中耗费的时间过长。后来换成使用Parallel.ForEach来进行循环。 一开始认为, 数据比较大时,Parallel.ForEach肯定比 ForEach效率高,后来发现,其实并不是这样。

我用了1000万次循环测试:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{

Stopwatch Watch1 = new Stopwatch();
Watch1.Start();
List<entityA> source = new List<entityA>();
for (int i = 0; i < 10000000; i++)
{
source.Add(new entityA
{
name = "悟空" + i,
sex = i % 2 == 0 ? "男" : "女",
age = i
});
}
Watch1.Stop();

Console.WriteLine("list循环插入耗时:" + Watch1.ElapsedMilliseconds);
Stopwatch Watch2 = new Stopwatch();
Watch2.Start();
loop1(source);
Watch2.Stop();
Console.WriteLine("一般for循环耗时:" + Watch2.ElapsedMilliseconds);

Stopwatch Watch3 = new Stopwatch();
Watch3.Start();
loop2(source);
Watch3.Stop();
Console.WriteLine("一般foreach循环耗时:" + Watch3.ElapsedMilliseconds);

Stopwatch Watch4 = new Stopwatch();
Watch4.Start();
loop3(source);
Watch4.Stop();
Console.WriteLine("并行for循环耗时:" + Watch4.ElapsedMilliseconds);

Stopwatch Watch5 = new Stopwatch();
Watch5.Start();
loop4(source);
Watch5.Stop();
Console.WriteLine("并行foreach循环耗时:" + Watch5.ElapsedMilliseconds);
Console.ReadLine();
}
//普通的for循环
static void loop1(List<entityA> source)
{
int count = source.Count();
for (int i = 0; i < count; i++)
{
source[0].age= + 10;
//System.Threading.Thread.Sleep(10);
}
}

//普通的foreach循环
static void loop2(List<entityA> source)
{
foreach (entityA item in source)
{
item.age =+ 10;
//System.Threading.Thread.Sleep(10);
}
}

//并行的for循环
static void loop3(List<entityA> source)
{
int count = source.Count();
Parallel.For(0, count, item =>
{
//source[count].age= source[count].age + 10;
//System.Threading.Thread.Sleep(10);
});
}

//并行的foreach循环
static void loop4(List<entityA> source)
{
Parallel.ForEach(source, item =>
{
item.age = item.age + 10;
//System.Threading.Thread.Sleep(10);
});
}
}

//简单的实体
class entityA
{
public string name { set; get; }
public string sex { set; get; }
public int age { set; get; }
}
}

运行结果:

结果居然是并行比一般的循环还耗时,但这是为什么呢?

这是因为循环体内执行的任务开销太小,仅仅是age+10 而已。微软的文章已经指出任务的开销大小对并行任务的影响。如果任务很小,那么由于并行管理的附加开销(任务分配,调度,同步等成本),可能并行执行并不是优化方案。这也是上述程序Foreach与For效率高出的原因。

基于这一点,我们对程序进行调整,循环1000次,每次里面线程sleep(10),这样我们试试。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{

Stopwatch Watch1 = new Stopwatch();
Watch1.Start();
List<entityA> source = new List<entityA>();
for (int i = 0; i < 1000; i++)
{
source.Add(new entityA
{
name = "悟空" + i,
sex = i % 2 == 0 ? "男" : "女",
age = i
});
}
Watch1.Stop();

Console.WriteLine("list循环插入耗时:" + Watch1.ElapsedMilliseconds);
Stopwatch Watch2 = new Stopwatch();
Watch2.Start();
loop1(source);
Watch2.Stop();
Console.WriteLine("一般for循环耗时:" + Watch2.ElapsedMilliseconds);

Stopwatch Watch3 = new Stopwatch();
Watch3.Start();
loop2(source);
Watch3.Stop();
Console.WriteLine("一般foreach循环耗时:" + Watch3.ElapsedMilliseconds);

Stopwatch Watch4 = new Stopwatch();
Watch4.Start();
loop3(source);
Watch4.Stop();
Console.WriteLine("并行for循环耗时:" + Watch4.ElapsedMilliseconds);

Stopwatch Watch5 = new Stopwatch();
Watch5.Start();
loop4(source);
Watch5.Stop();
Console.WriteLine("并行foreach循环耗时:" + Watch5.ElapsedMilliseconds);
Console.ReadLine();
}
//普通的for循环
static void loop1(List<entityA> source)
{
int count = source.Count();
for (int i = 0; i < count; i++)
{
source[0].age= + 10;
System.Threading.Thread.Sleep(10);
}
}

//普通的foreach循环
static void loop2(List<entityA> source)
{
foreach (entityA item in source)
{
item.age =+ 10;
System.Threading.Thread.Sleep(10);
}
}

//并行的for循环
static void loop3(List<entityA> source)
{
int count = source.Count();
Parallel.For(0, count, item =>
{
//source[count].age= source[count].age + 10;
System.Threading.Thread.Sleep(10);
});
}

//并行的foreach循环
static void loop4(List<entityA> source)
{
Parallel.ForEach(source, item =>
{
item.age = item.age + 10;
System.Threading.Thread.Sleep(10);
});
}
}

//简单的实体
class entityA
{
public string name { set; get; }
public string sex { set; get; }
public int age { set; get; }
}
}

执行结果:

效率一目了然。

这样的结果认证了我们上面的结论。当我们在循环中执行时间过长时,我们需要采用并行循环,效率较高。当时间过短,我们需要用foreach和for.
---------------------
作者:李江涛-Sir
来源:CSDN
原文:https://blog.csdn.net/li315171406/article/details/78450534
版权声明:本文为博主原创文章,转载请附上博文链接!

C# 多线程 Parallel.ForEach 和 ForEach 效率问题研究及理解的更多相关文章

  1. C# 多线程 Parallel.For 和 For 谁的效率高?那么 Parallel.ForEach 和 ForEach 呢?

    还是那句话:十年河东,十年河西,莫欺少年穷. 今天和大家探讨一个问题:Parallel.For 和 For 谁的效率高呢? 从CPU使用方面而言,Parallel.For 属于多线程范畴,可以开辟多个 ...

  2. php代码优化系列 -- array_walk 和 foreach, for 的效率的比较

    实验是我学习计算机科学的一个重要方法,计算机科学不是简单的智力游戏,它本质上来说不是一门科学,而是一个改造世界的工具.数学方法和实验方法是计算机研究的基本方法,也是我们学习的基本方法,数学锻炼我们的思 ...

  3. php代码优化 -- array_walk 和 foreach, for 的效率的比较

    <?php /** * array_walk 和 foreach, for 的效率的比较. * 我们要测试的是foreach, for, 和 array_walk的效率的问题. */ //产生一 ...

  4. C# for 和 foreach的执行效率

    for和foreach哪个执行效率快,相信很多人都会说当然是foreach快啊,在我实验之前我也是这么认为的,直到今天.费话不多说,下面是测试的结果,区分Debug和Release,数据采用int[] ...

  5. java8 for ,forEach ,lambda forEach , strean forEach , parller stream forEach, Iterator性能对比

    java8 for ,forEach ,Iterator,lambda forEach ,lambda  strean forEach , lambda parller stream forEach性 ...

  6. Parallel Programming-Paralle.For && ForEach

    本文主要介绍Parallel.For以及Parallel.ForEach.Parallel.For是普通步长为1的for循环的并行代替方案.Parallel.ForEach是以集合为基准进行循环的fo ...

  7. mybatis中foreach参数过多效率很慢的优化

    foreach 后面in 传入的参数有1万条,#和$是有效率区别的,$的效率远高于#,上篇文章做了比较. 但没达到我的理想结果. 1. 更改方式,把foreach 去掉,改成拼装方式, 参数直接拼装成 ...

  8. Foreach嵌套Foreach速度慢优化方案

    有时候这样的效率还可以,但是只要牵涉到操作数据库,那就GAMEOVER.. 最近在维护项目,一个Foreach循环,4分半才能出来结果. 代码: foreach ($content as $key = ...

  9. 多线程Parallel和Task

    不管是Parallel还是Task,最里面都是线程池(里面是线程)当开启多个任务后,系统会根据当前的线程池的资源进行分配,任务则进行等待Parallel可以对系统的CPU进行设置,可以最大程度上榨干系 ...

随机推荐

  1. Python __init__函数的使用

    class Cat: def __init__(self,_name): self.name = _name def eat(self): print("i am eating ." ...

  2. Qt 程序打包发布总结

    1.  概述 当我们用QT写好了一个软件,要把你的程序分享出去的时候,不可能把编译的目录拷贝给别人去运行.编译好的程序应该是一个主程序,加一些资源文件,再加一些动态链接库,高大上一些的还可以做一个安装 ...

  3. 1、Maven安装教程详解

    一.准备工作  1.确定电脑上已经成功安装jdk7.0以上版本                 2.win10操作系统                 3.maven安装包            下载 ...

  4. ubuntu 安装bazel

    https://docs.bazel.build/versions/master/install-ubuntu.html#install-with-installer-ubuntu

  5. Linux 下如何处理包含空格和特殊字符的文件名

    Linux 下如何处理包含空格和特殊字符的文件名 作者: Avishek Kumar 译者: LCTT zpl1025 | 2015-07-08 07:47   评论: 12 收藏: 9 分享: 1 ...

  6. 【Python】Python加lxml实现图片解析下载功能

    1.下载网页:OpenHtml.py import urllib.request from urllib.parse import quote class HtmlLoader(object): de ...

  7. 第三百七十三节,Django+Xadmin打造上线标准的在线教育平台—创建用户app,在models.py文件生成3张表,用户表、验证码表、轮播图表

    第三百七十三节,Django+Xadmin打造上线标准的在线教育平台—创建用户app,在models.py文件生成3张表,用户表.验证码表.轮播图表 创建Django项目 项目 settings.py ...

  8. 《深入理解Java虚拟机》读书笔记:Java内存区域

    xmind文件下载地址

  9. MyBatis环境配置及入门

    Mybatis 开发环境搭建,选择: MyEclipse8.5 版本,mysql 5.5, jdk 1.8, mybatis3.2.3.jar 包.这些软件工具均可以到各自的官方网站上下载. 整个过程 ...

  10. 【转】在64位windows下使用instsrv.exe和srvany.exe创建windows服务

    本文转自:https://www.iflym.com/index.php/computer-use/201205020001.html 在32位的windows下,包括windows7,windows ...