zoukankan      html  css  js  c++  java
  • 任务Task系列之Parallel的静态For,ForEach,Invoke方法

      本文参考书籍《CLR via C#》  

      一些常见的编程情形呢都可以通过任务来提升性能,为了简化编程,静态System.Threading.Tasks.Parallel封装了这些静态方法,其实它的内部仍然使用了Task对象,只是一些便捷编程的语法糖,但是十分好用。

      比如常见的循环:

      for(Int32 i=0;i<1000;i++) DoSometing();

      就可以用Parallel的for方法:

      Parallel.For(0, 10000, i => DoSometing(i));

      类似的有一个集合:

      foreach(var item in collection) DoSometing(item)

      就可用Palallel的ForEach:

      Palallel.ForEach(collection,item=>DoSometing(item))

      如果既可以用For,也可以用ForEach,那么建议使用For,因为它执行的更快,

      如果要执行多个方法:

      Method1();

      Method2();

      Method3();

      就可以并行执行:

      Palallel.Invole(

      ()=>Method1(),

      ()=>Method2(),

      ()=>Mathod3()

      );

      比如我们有一个求和的方法:

    private static Int32 NumValue(Int32 n)
            {
                Int32 sum = 0;
                for (int i = 0; i < n; i++)
                {
                    sum += i;
                }
                return sum;
            }

      如果使用Parallel.For()就可以写成

    private static Int32 ParallelNumValue(Int32 n)
            {
                Int32 sum=0;
                Parallel.For(1, n, i => { sum += i; });
                return sum;
            }

      我们求累加到5000000,看一下串行求和和并行求和耗时的差别:

    static void Main(string[] args)
            {
                Console.WriteLine("============耗时比较=============");
                {
                    System.Diagnostics.Stopwatch sw=new System.Diagnostics.Stopwatch();
                    sw.Start();
                    Int32 a = NumValue(5000000);
                    sw.Stop();
                    Console.WriteLine("串行求和得{0},耗时{1}ms",a, sw.ElapsedMilliseconds);
                    sw.Restart();
                    sw.Stop();
                    Int32 b = NumValue(5000000);
                    Console.WriteLine("并行求和得{0},耗时{1}ms",b,sw.ElapsedMilliseconds);
                }
                Console.WriteLine("=================================");
                Console.ReadLine();
            }

      测试结果如下:

      

      可见串行要更耗时些。

      Parallel的所有方法都让调用线程参与处理。从资源利用的角度说,这是一件好事,因为我们不望调用线程停下来(阻塞),等线程池线程做完所有工作オ能继续。然而,如果调用线程在线程池线程完成自己的那一部分工作之前完成工作,调用线程会将自己挂起,直到所有工作完成。这也是一件好事,因为这提供了和使用普通for或 foreach循环时相同的语义:线程要在所有工作完成后才继续运行。还要注意,如果任何操作抛出未处理的异常,你调用的Parallel方法最后会抛出一个AggregateException。但这不是说需要对自己的源代码进行全文替换,将for循环替换成对 Parallel.For的调用,将forech循环替换成对 Parallel. Foreach的调用。调用 Parallel的方法时有一个很重要的前提条件:工作项必须能并行执行!所以,如果工作必须顺序执行,就不要使用 Paralel的方法。另外,要避免会修改任何共享数据的工作项,否则多个线程同时处理可能会损坏数据。解決这个问题一般的办法是围绕数据访问添加线程同步锁。但这样一次就只能有一个线程访问数据,无法享受并行处理多个项所带来的好处。
      另外, Parallel的方法本身也有开销:委托对象必须分配,而针对每个工作项都要调用一次这些委托。如果有大量可由多个线程处理的工作项,那么也许能获得性能的提升。另外,如果每一项都涉及大量工作,那么通过委托来调用所产生的性能损失是可以忽略不计的。但如果只为区区几个工作项使用 Parallel的方法,或者为处理得非常快的工作项使用Parallel的方法,就会得不偿失,反而降低性能。
      

      

  • 相关阅读:
    团队展示&选题
    结对编程(JAVA实现)
    wc项目(node.js实现)
    复审与事后分析
    事后诸葛亮分析报告
    Alpha阶段项目复审
    测试与发布
    Scrum 冲刺第五篇
    Scrum 冲刺第一篇
    项目冲刺
  • 原文地址:https://www.cnblogs.com/mohanchen/p/9398244.html
Copyright © 2011-2022 走看看