转载地址见一,下同。

5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq

在上一篇博客5天玩转C#并行和多线程编程 —— 第一天 认识Parallel中,我们学习了Parallel的用法。并行编程,本质上是多线程的编程,那么当多个线程同时处理一个任务的时候,必然会出现资源访问问题,及所谓的线程安全。就像现实中,我们开发项目,就是一个并行的例子,把不同的模块分给不同的人,同时进行,才能在短的时间内做出大的项目。如果大家都只管自己写自己的代码,写完后发现合并不到一起,那么这种并行就没有了意义。
并行算法的出现,随之而产生的也就有了并行集合,及线程安全集合;微软向的也算周到,没有忘记linq,也推出了linq的并行版本,plinq - Parallel Linq.
一、并行集合 —— 线程安全集合                                                                
并行计算使用的多个线程同时进行计算,所以要控制每个线程对资源的访问,我们先来看一下平时常用的List<T>集合,在并行计算下的表现,新建一个控制台应用程序,添加一个PEnumerable类(当然你也直接写到main方法里面测试,建议分开写),写如下方法:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Concurrent;namespace ThreadPool
{public class PEnumerable{public static void ListWithParallel(){List<int> list = new List<int>();Parallel.For(0, 10000, item =>{list.Add(item);});Console.WriteLine("List's count is {0}",list.Count());}}
}

点击F5运行,得到如下结果:

看到结果中显示的5851,但是我们循环的是10000次啊!怎么结果不对呢?这是因为List<T>是非线程安全集合,意思就是说所有的线程都可以修改他的值。

下面我们来看下并行集合 —— 线程安全集合,在System.Collections.Concurrent命名空间中,首先来看一下ConcurrentBag<T>泛型集合,其用法和List<T>类似,先来写个方法测试一下:

public static void ConcurrentBagWithPallel(){ConcurrentBag<int> list = new ConcurrentBag<int>();Parallel.For(0, 10000, item =>{list.Add(item);});Console.WriteLine("ConcurrentBag's count is {0}", list.Count());}

同时执行两个方法,结果如下:

可以看到,ConcurrentBag集合的结果是正确的。下面我们修改代码看看ConcurrentBag里面的数据到底是怎么存放的,修改代码如下:

public static void ConcurrentBagWithPallel(){ConcurrentBag<int> list = new ConcurrentBag<int>();Parallel.For(0, 10000, item =>{list.Add(item);});Console.WriteLine("ConcurrentBag's count is {0}", list.Count());int n = 0;foreach(int i in list){if (n > 10)break;n++;Console.WriteLine("Item[{0}] = {1}",n,i);}Console.WriteLine("ConcurrentBag's max item is {0}", list.Max());}

先来看一下运行结果:

可以看到,ConcurrentBag中的数据并不是按照顺序排列的,顺序是乱的,随机的。我们平时使用的Max、First、Last等linq方法都还有。其时分类似Enumerable的用法,大家可以参考微软的MSDN了解它的具体用法。

关于线程安全的集合还有很多,和我们平时用的集合都差不多,比如类似Dictionary的ConcurrentDictionary,还有ConcurrentStack,ConcurrentQueue等。

二、Parallel Linq的用法及性能

1、AsParallel

前面了解了并行的For和foreach,今天就来看一下Linq的并行版本是怎么样吧?为了测试,我们添加一个Custom类,代码如下:

public class Custom{public string Name { get; set; }public int Age { get; set; }public string Address { get; set; }}

写如下测试代码:

 public static void TestPLinq(){Stopwatch sw = new Stopwatch();List<Custom> customs = new List<Custom>();for (int i = 0; i < 2000000; i++){customs.Add(new Custom() { Name = "Jack", Age = 21, Address = "NewYork" });customs.Add(new Custom() { Name = "Jime", Age = 26, Address = "China" });customs.Add(new Custom() { Name = "Tina", Age = 29, Address = "ShangHai" });customs.Add(new Custom() { Name = "Luo", Age = 30, Address = "Beijing" });customs.Add(new Custom() { Name = "Wang", Age = 60, Address = "Guangdong" });customs.Add(new Custom() { Name = "Feng", Age = 25, Address = "YunNan" });}sw.Start();var result = customs.Where<Custom>(c => c.Age > 26).ToList();sw.Stop();Console.WriteLine("Linq time is {0}.",sw.ElapsedMilliseconds);sw.Restart();sw.Start();var result2 = customs.AsParallel().Where<Custom>(c => c.Age > 26).ToList();sw.Stop();Console.WriteLine("Parallel Linq time is {0}.", sw.ElapsedMilliseconds);}

其实也就是加了一个AsParallel()方法,下面来看下运行结果:

时间相差了一倍,不过有时候不会相差这么多,要看系统当前的资源利用率。大家可以多测试一下。

其实,AsParallel()这个方法可以应用与任何集合,包括List<T>集合,从而提高查询速度和系统性能。

2、GroupBy方法

在项目中,我们经常要对数据做处理,比如分组统计,我们知道在linq中也可以实现,今天来学习一下新的ToLookup方法,写一个测试方法,代码如下:

public static void OrderByTest(){Stopwatch stopWatch = new Stopwatch();List<Custom> customs = new List<Custom>();for (int i = 0; i < 2000000; i++){customs.Add(new Custom() { Name = "Jack", Age = 21, Address = "NewYork" });customs.Add(new Custom() { Name = "Jime", Age = 26, Address = "China" });customs.Add(new Custom() { Name = "Tina", Age = 29, Address = "ShangHai" });customs.Add(new Custom() { Name = "Luo", Age = 30, Address = "Beijing" });customs.Add(new Custom() { Name = "Wang", Age = 60, Address = "Guangdong" });customs.Add(new Custom() { Name = "Feng", Age = 25, Address = "YunNan" });}stopWatch.Restart();var groupByAge = customs.GroupBy(item => item.Age).ToList();foreach (var item in groupByAge){Console.WriteLine("Age={0},count = {1}", item.Key, item.Count());}stopWatch.Stop();Console.WriteLine("Linq group by time is: " + stopWatch.ElapsedMilliseconds);stopWatch.Restart();var lookupList = customs.ToLookup(i => i.Age);foreach (var item in lookupList){Console.WriteLine("LookUP:Age={0},count = {1}", item.Key, item.Count());}stopWatch.Stop();Console.WriteLine("LookUp group by time is: " + stopWatch.ElapsedMilliseconds);}

运行结果如下:

ToLookup方法是将集合转换成一个只读集合,所以在大数据量分组时性能优于List.大家可以查阅相关资料,这里由于篇幅问题,不再细说。

5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq相关推荐

  1. 5天玩转C#并行和多线程编程 —— 第五天 多线程编程大总结

    5天玩转C#并行和多线程编程 -- 第五天 多线程编程大总结 5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 -- 第一天 认识Parallel 5天玩转C#并行和多线程编程 ...

  2. 5天玩转C#并行和多线程编程 —— 第四天 Task进阶

     一.Task的嵌套 Task中还可以再嵌套Task,Thread中能不能这样做,我只能说我是没这样写过.Task中的嵌套,我感觉其实也可以分开来写,不过嵌套起来会方便管理一点.Task中的嵌套分为两 ...

  3. C#并行和多线程编程

    参考:https://www.cnblogs.com/yunfeifei/p/3993401.html 和 https://www.cnblogs.com/rjjs/p/5583722.html  推 ...

  4. python中的多线程求值串行和并行_python多线程和多进程——python并行编程实验

    工作中经常涉及到加速程序的运行,除了代码逻辑的优化,算法的优化之外,还经常使用的一招就是并发编程.至于python的并型编程这一块.说到并行编程,我们不得不谈线程和进程这两个概念: + 进程:对于操作 ...

  5. Matlab多核CPU并行和多线程

    简介 这里需要明白的概念有:多核.多进程.多线程.并行计算.并发计算的区别. 什么是多核 在计算机设计早期,为了响应更多计算性能的需要,单处理器系统发展成为多处理器系统.更现代的.类似的系统设计趋势是 ...

  6. 多线程编程技术开发资料

    多线程编程技术开发资料 目录 Win32 多线程的性能(1)... 1 Win32 多线程的性能(2)... 10 关于多线程的一些细节... 23 用VC++5.0 实 现 多 线 程 的 调 度  ...

  7. Linux环境多线程编程基础设施

    Linux环境多线程编程基础设施 来源:Yebangyu 本文介绍多线程环境下并行编程的基础设施.主要包括: Volatile __thread Memory Barrier __sync_synch ...

  8. python多线程教程_Python多线程编程教程【2小时学会】

    Python多线程编程教程[2小时学会] 中级共14课 从0开始学习python多任务编程,想了解python高并发实现,从基础到实践,通过知识点 + 案例教学法帮助你想你想迅速掌握python多任务 ...

  9. python多核多线程编程实例_Python多线程

    多线程基础概念 并行与并发并行:同时处理多个任务,必须在多核环境下 一段时间内同时处理多个任务,单核也可以并发 并发手段线程:内核空间的调度 进程:内核空间的调度 协程:用户空间的调度 线程可以允许程 ...

  10. 计算机是如何工作的,Java多线程编程

    一.冯诺依曼体系 现代的计算机,大多遵守 冯诺依曼体系结构 (Von Neumann Architecture) CPU 中央处理器: 进行算术运算和逻辑判断. AMD Ryzen 7 580OU w ...

最新文章

  1. 【本人秃顶程序员】使用Spring Cloud Stream和RabbitMQ实现事件驱动的微服务
  2. APP市场火热的背后 云计算技术不是核心竞争力
  3. Python爬虫基础面试题为2020年初大学生就业做准备(文末附教程)
  4. 正则表达式入门之使用元字符
  5. java迭代器用途_各位JAVA前辈,迭代器使用报错。
  6. mysql 2005开发版,SQL server 2019 开发版下载
  7. Android之build.gradle配置签名
  8. 技术人必看:15张图对比高效与瞎忙的区别!
  9. 如何在今日头条上持续生产优质内容
  10. [leetcode] Power of Two 判断一个数是否是2的平方
  11. 鼠标放在一个连接上,会显示图片(类似tooltip)
  12. Thread.sleep(0)的意义
  13. java 24种设计模式
  14. 汉字转拼音接口 get请求 无需注册
  15. 鸡兔同笼python程序怎么写_梦见鸡_周公解梦梦到鸡是什么意思_做梦梦见鸡好不好_周公解梦官网...
  16. 知识点滴- BC和BCE的区别
  17. 歌手大奖赛(C语言)
  18. 【分享】“飞书自建“在集简云平台集成应用的常见问题与解决方案
  19. Pycharm启动后总 indices... indexing的问题
  20. kaggle之识别谷歌街景图片中的字母

热门文章

  1. supervisor来管理和监控进程
  2. Java prepare
  3. linux PS1 变量设置
  4. Packet Tracert 5.0 使用教程
  5. 系统补丁安静安装参数
  6. 【Shell】ps -ef 和ps aux
  7. vue+elementui搭建后台管理界面(6登录和菜单权限控制)
  8. 禅道项目管理工具环境搭建
  9. loj #6122. 「网络流 24 题」航空路线问题
  10. SQL数据库中日期时间类型,按日期group by 实现