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 List的一些相关操作

    把一些基础的东西归类整理,作记录. 添加元素 a=[7,8,9,10] a.append('a') #在最后位置添加 a.insert(1,'b') #在指定位置添加     删除元素 del a[1 ...

  2. linux下安装jre运行环境

    上官网下载安装文件:点击打开链接 文件名:jre-8u65-linux-x64.gz安装步骤1.解压tar -xzvf jre-8u65-linux-x64.gz2.将解压后的文件放到/usr/lib ...

  3. android 避免线程的重复创建(HandlerThread、线程池)

    最近在android开发中,用到都是new Thread(){...}.start()这种方式.本来这样是可以,但是最近突然爆出Performing stop of activity that is ...

  4. HBase启动后发现HMaster进程消失了

    HMaster没起来很多原因,这次看日志是这个.详细请看:http://www.bkjia.com/yjs/982064.html Hbase:namespace异常处理,hbase异常处理 Hbas ...

  5. python with 语句妙用

    class aa(): def bb(self): print("hhhh") return "hello world" def __enter__(self) ...

  6. python2 python3 字符串 编码格式 处理

    使用python的ctypes调用c语言中的函数,传入字符串,打印输出异常.解决方法记录于此. 参考连接: http://blog.csdn.net/u011546806/article/detail ...

  7. [转]jQuery选择器 (详解)

    1).基本 #id 根据给定的ID匹配一个元素.例如:$("#id")element 根据给定的元素名匹配所有元素.例如:$("div").class 根据给定 ...

  8. e799. 限制JSlider的数值在标记以内

    By default, the slider can take on any value from the minimum to the maximum. It is possible to conf ...

  9. 文字超过字符长度 显示… 点点点 jquery

    在 script脚本区域里面定义如下方法 jQuery.fn.limit = function() { var self = $("[limit]"); self.each(fun ...

  10. html固定宽度下拉框内容显示不全问题解决方法

    不少时候在页面中为了布局的需要,下拉列表<select>的宽度需要设成比较小的值,这时如果恰巧它包含的选择项<option>的内容比较长,那么超出select宽度的部分将会被截 ...