5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq
转载地址见一,下同。
5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq
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相关推荐
- 5天玩转C#并行和多线程编程 —— 第五天 多线程编程大总结
5天玩转C#并行和多线程编程 -- 第五天 多线程编程大总结 5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 -- 第一天 认识Parallel 5天玩转C#并行和多线程编程 ...
- 5天玩转C#并行和多线程编程 —— 第四天 Task进阶
一.Task的嵌套 Task中还可以再嵌套Task,Thread中能不能这样做,我只能说我是没这样写过.Task中的嵌套,我感觉其实也可以分开来写,不过嵌套起来会方便管理一点.Task中的嵌套分为两 ...
- C#并行和多线程编程
参考:https://www.cnblogs.com/yunfeifei/p/3993401.html 和 https://www.cnblogs.com/rjjs/p/5583722.html 推 ...
- python中的多线程求值串行和并行_python多线程和多进程——python并行编程实验
工作中经常涉及到加速程序的运行,除了代码逻辑的优化,算法的优化之外,还经常使用的一招就是并发编程.至于python的并型编程这一块.说到并行编程,我们不得不谈线程和进程这两个概念: + 进程:对于操作 ...
- Matlab多核CPU并行和多线程
简介 这里需要明白的概念有:多核.多进程.多线程.并行计算.并发计算的区别. 什么是多核 在计算机设计早期,为了响应更多计算性能的需要,单处理器系统发展成为多处理器系统.更现代的.类似的系统设计趋势是 ...
- 多线程编程技术开发资料
多线程编程技术开发资料 目录 Win32 多线程的性能(1)... 1 Win32 多线程的性能(2)... 10 关于多线程的一些细节... 23 用VC++5.0 实 现 多 线 程 的 调 度 ...
- Linux环境多线程编程基础设施
Linux环境多线程编程基础设施 来源:Yebangyu 本文介绍多线程环境下并行编程的基础设施.主要包括: Volatile __thread Memory Barrier __sync_synch ...
- python多线程教程_Python多线程编程教程【2小时学会】
Python多线程编程教程[2小时学会] 中级共14课 从0开始学习python多任务编程,想了解python高并发实现,从基础到实践,通过知识点 + 案例教学法帮助你想你想迅速掌握python多任务 ...
- python多核多线程编程实例_Python多线程
多线程基础概念 并行与并发并行:同时处理多个任务,必须在多核环境下 一段时间内同时处理多个任务,单核也可以并发 并发手段线程:内核空间的调度 进程:内核空间的调度 协程:用户空间的调度 线程可以允许程 ...
- 计算机是如何工作的,Java多线程编程
一.冯诺依曼体系 现代的计算机,大多遵守 冯诺依曼体系结构 (Von Neumann Architecture) CPU 中央处理器: 进行算术运算和逻辑判断. AMD Ryzen 7 580OU w ...
最新文章
- 【本人秃顶程序员】使用Spring Cloud Stream和RabbitMQ实现事件驱动的微服务
- APP市场火热的背后 云计算技术不是核心竞争力
- Python爬虫基础面试题为2020年初大学生就业做准备(文末附教程)
- 正则表达式入门之使用元字符
- java迭代器用途_各位JAVA前辈,迭代器使用报错。
- mysql 2005开发版,SQL server 2019 开发版下载
- Android之build.gradle配置签名
- 技术人必看:15张图对比高效与瞎忙的区别!
- 如何在今日头条上持续生产优质内容
- [leetcode] Power of Two 判断一个数是否是2的平方
- 鼠标放在一个连接上,会显示图片(类似tooltip)
- Thread.sleep(0)的意义
- java 24种设计模式
- 汉字转拼音接口 get请求 无需注册
- 鸡兔同笼python程序怎么写_梦见鸡_周公解梦梦到鸡是什么意思_做梦梦见鸡好不好_周公解梦官网...
- 知识点滴- BC和BCE的区别
- 歌手大奖赛(C语言)
- 【分享】“飞书自建“在集简云平台集成应用的常见问题与解决方案
- Pycharm启动后总 indices... indexing的问题
- kaggle之识别谷歌街景图片中的字母