zoukankan      html  css  js  c++  java
  • 并行编程_Parallel

    一、Parallel.Invoke执行多个方法

    没有特定执行顺序,利用cpu多核并发执行,在运行并行方法前都会产生一些额外的开销,我们一定要测量运行结果相比没有并行是否有优化

      #region Parallel.Invoke
                Stopwatch watch = new Stopwatch();
                watch.Start();
                Parallel.Invoke(Pinvoke1, Pinvoke2);
                watch.Stop();
                Console.WriteLine("Parallel run " + watch.ElapsedMilliseconds + " ms");
                watch.Reset();
                watch.Start();
                Pinvoke1();
                Pinvoke2();
                watch.Stop();
                Console.WriteLine("Normal run " + watch.ElapsedMilliseconds + " ms");
                Console.ReadKey();
    
                #endregion Parallel.Invoke
    
      private static void Pinvoke1()
            {
                Thread.Sleep(3000);
                Console.WriteLine("Pinvoke1 ThreadId="+Thread.CurrentContext.ContextID);
            }
    
            private static void Pinvoke2()
            {
                Thread.Sleep(2000);
                Console.WriteLine("Pinvoke2 ThreadId=" + Thread.CurrentContext.ContextID);
            }
    

     结果:

    二、Parallel.For   每一次迭代一会当作一个任务交给一个线程,线程可能会重用,cpu决定

       Stopwatch watch = new Stopwatch();
                watch.Start();
    
                for (int i = 0; i < 5; i++)
                {
                    Console.WriteLine(i);
                    Thread.Sleep(1000);
                }
                watch.Stop();
                Console.WriteLine(watch.Elapsed);
           
                watch.Restart();
                Parallel.For(0, 5, i =>
                {
                    Console.WriteLine("===" + Thread.CurrentThread.ManagedThreadId + "===");
                    Console.WriteLine(i);
                    Thread.Sleep(1000);
                });
                watch.Stop();
                Console.WriteLine(watch.Elapsed);
                Console.ReadKey();
    

    效果还是非常明显的,但是有个问题是Parallel.For是并行执行,每次迭代基本都会启用新线程,那么我们共用一个全局变量的时候,必须要加锁,出现资源等待,这时用并行就不合适了:示例如下:

    object asyncObj = new object();
                long value = 0;
                Stopwatch watch = new Stopwatch();
                watch.Start();
                for (int i = 0; i < 9999; i++)
                {
                    for (int j = 0; j < 19999; j++)
                    {
                        value++;
                    }
                }
                watch.Stop();
                Console.WriteLine("正常运行是" + watch.ElapsedMilliseconds + " ms");
                watch.Restart();
                Parallel.For(0, 9999, i =>
                {
                    for (int j = 0; j < 19999; j++)
                    {
                        lock (asyncObj)
                        {
                            value++;
                        }
                    }
                });
                watch.Stop();
                Console.WriteLine("并行运行是" + watch.ElapsedMilliseconds + " ms");
                Console.ReadKey();

    三、Parallel.ForEach  都foreach一样,只不过是并行的,也是每次循环一个线程处理

        List<Person> list = new List<Person>();
                for (int i = 1; i < 100; i++)
                {
                    list.Add(new Person
                    {
                        Age = i,
                        Name = "Name" + i
                    });
                }
                Stopwatch watch = new Stopwatch();
                watch.Start();
                Parallel.ForEach(list, p =>
                {
                    Console.WriteLine("===" + Thread.CurrentThread.ManagedThreadId + "===");
                    Console.WriteLine(p.Name);
                });
                watch.Stop();
                Console.ReadKey();
    

    四、并行中断

    ParallelLoopState:

    1、Break-并行循环执行了当前迭代后尽快地停止执行。

    //更改方法stop下面的示例,运行结果不一定哦,49,50都出现了

    2、Stop-直接停止

    //结果是50
      List<Person> list=new List<Person>();
                Parallel.For(0, 100, (num, state) =>
                {
                    if (num<50)
                    {
                        list.Add(new Person() {Age = num});
                    }
                    else
                    {
                        state.Stop();
                    }
                });
                Console.WriteLine(list.Count);
    

    五、异常处理

    并行执行的时候使用AggregateException获取全部异常,用Exception只能获取其中一个;

                try
                {
                    Parallel.Invoke(Pinvoke1, Pinvoke2);
                }
                catch (AggregateException aggregateException)
                {
                    foreach (var innerException in aggregateException.InnerExceptions)
                    {
                        Console.WriteLine(innerException.Message);
                    }
                }
    
        private static void Pinvoke1()
            {
                Thread.Sleep(3000);
                Console.WriteLine("Pinvoke1 ThreadId=" + Thread.CurrentContext.ContextID);
                throw new Exception("并行任务1抛出异常");
            }
    
            private static void Pinvoke2()
            {
                Thread.Sleep(2000);
                Console.WriteLine("Pinvoke2 ThreadId=" + Thread.CurrentContext.ContextID);
                throw new Exception("并行任务2抛出异常");
            }
    

     六、并行Linq (AsParallel,可以应用任何集合,提高处理速度)

      Stopwatch watch=new Stopwatch();
                List<Person> list = new List<Person>();
                Parallel.For(0,10000,p =>
                {
                    list.Add(new Person() {Age = p,Name = "name"+p});//注意并行会出现有空对象的现象;也可以调用Invoke方法,里面写for循环就不会出现空对象
                });
                Console.WriteLine(list.Count);
                watch.Start();
                Console.WriteLine(list.Count);
                var persons = list.Where(c=>c!=null&&c.Age>100).ToList();
                watch.Stop();
                Console.WriteLine(watch.ElapsedMilliseconds);
                watch.Restart();
                var parallelPersons = list.AsParallel().Where(c=> c != null && c.Age>100).ToList();
                watch.Stop();
                Console.WriteLine(watch.ElapsedMilliseconds);
                Console.ReadKey();
    

      

  • 相关阅读:
    第五次博客作业
    第三次博客作业
    个人简介
    实验三
    实验二
    实验一
    《构建之法》心得体会
    第三次博客园作业
    软件测试实验二
    个人简历
  • 原文地址:https://www.cnblogs.com/entclark/p/8026815.html
Copyright © 2011-2022 走看看