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

C# 多线程 Parallel.ForEach 和 ForEach 效率问题研究及理解最近要做一个大数据dataTable循环操作,开始发现运用foreach,进行大数据循环,并做了一些逻辑处理。在循环中耗费的时间过长。后来换成使用Parallel.ForEach来进行循环。一开始认为, 数据比较大时,Parallel.ForEach肯定比 ForEach效率高,后来发现,其实并不是这样。我用了1000万次循环测试:{CSDN:CODE:2601125}

大家好,又见面了,我是你们的朋友全栈君。

      最近要做一个大数据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; }
    }
}

运行结果:

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

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

这是因为循环体内执行的任务开销太小,仅仅是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; }
    }
}

执行结果:

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

效率一目了然。

这样的结果认证了我们上面的结论。当我们在循环中执行时间过长时,我们需要采用并行循环,效率较高。当时间过短,我们需要用foreach和for.

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/161789.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 使用VS2010打包软件详解!

    使用VS2010打包软件详解!使用VS2010下VisualStudioInstaller工程进行软件安装包制作        软件在功能开发实现后,其实并没有真正的完成。对于一个专业的开发者来说,Release软件应该是以安装版本的形式进行发布的,这篇文章将具体介绍如何使用VS2010下VisualStudioInstaller进行打包软件。Setp1.首先建立VisualStudio

    2025年5月31日
    2
  • rct429 java_RCT: RCT(Redis Computed Tomography) RCT 是一个通过解析rdb文件对redis内存结构分析的一站式平台。 支持对非集群/集群rdb文…[通俗易懂]

    Language:RCT(RedisComputedTomography)RCT是一个通过解析rdb文件对redis内存结构分析的一站式平台。支持对非集群/集群rdb文件分析、Slowlog查询与监控、ClientList查询与监控。GitHub第一时间更新,请移步查看!功能内存分析通过对rdb文件解析,分析Redis内存使用情况,支持多维度、多报表方式。支持手动、自动多种方式!提…

    2022年4月18日
    57
  • Java内存模型详解

    Java内存模型详解前几天,发了一篇文章,介绍了一下JVM内存结构、Java内存模型以及Java对象模型之间的区别。有很多小伙伴反馈希望可以深入的讲解下每个知识点。Java内存模型,是这三个知识点当中最晦涩难懂的一个,而且涉及到很多背景知识和相关知识。网上有很多关于Java内存模型的文章,在《深入理解Java虚拟机》和《Java并发编程的艺术》等书中也都有关于这个知识点的介绍。但是,很多人读完之后还是搞不清楚,甚…

    2022年6月3日
    32
  • ipv4地址分类_d类ipv4地址以什么开始

    ipv4地址分类_d类ipv4地址以什么开始ipv4地址:表示一个网络节点的网络地址总共可以产生40多亿ip地址,32位二进制数–表示用点分十进制IPv4地址由四段组成,每个字段是一个字节,8位,最大值是255,,IPv4地址由两部分组成,即网络地址和主机地址。网络地址表示其属于互联网的哪一个网络,主机地址表示其属于该网络中的哪一台主机,两者是主从关系。IPv4地址的四大类型标识的是网络中的某台主机。IPv4地址长度为32位,共4…

    2025年8月21日
    3
  • facade模式的好处_fa模式是什么意思

    facade模式的好处_fa模式是什么意思Facade模式使用Facade模式可以为互相关联在一起的错综复杂的类整理出高层接口(API)。其中的Facade角色可以让系统对外只有一个简单的接口(API)。而且,Facade角色还会考虑系统内部各个类之间的责任关系和依赖关系,按照正确的顺序调用各个类。示例程序示例程序类图Databasemportjava.io.FileInputStream;importjava.io….

    2025年7月28日
    3
  • VLAN的特点及作用_vlan特点和作用有哪些

    VLAN的特点及作用_vlan特点和作用有哪些VLAN的作用:把同一物理局域网内的不同用户逻辑地划分成不同的广播域,有助于控制流量、减少设备投资、简化网络管理、提高网络的安全性。VLAN的特点:1)区段化:将一个网络进行区段化,减少每个区段的主机数量,提高网络性能;2)灵活性:一般情况下无须更改物理网络与增加新设备及更改布线系统;3)安全性:VLAN间的通讯是在受控的方式下完成的。转载于:https://www.cnb…

    2022年8月10日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号