并行LINQ

.NET4在System.Linq命名空间中包含一个新类ParallelEnumerable,可以分解查询的工作使其分布在多个线程上.尽管Enumerable类给IEnumerable<T>接口定义了扩展方法,但ParallelEnumerable类的大多数扩展方法是ParallelQuery<TSource>类的扩展.一个重要的例外是AsParallel()方法,它扩展了IEnumerable<TSource>接口,返回ParallelQuery<TSource>类,所以正常的集合类可以以平行方式查询.

LINQ比较强大的是还提供了可并行处理的查询,这使得我们可以借助它来完成一些查询处理或处理并行操作.

先来说一下并行集合,并行计算使用的多个线程同时进行计算,所以要控制每个线程对资源的访问,我们先来看一下常用的List<T>集合,在并行计算下的表示:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace 并行集合和LINQ

{

class Program

{

static void Main(string[] args)

{

List<int> list = new List<int>();

Parallel.For(0, 10000, item =>

{

list.Add(item);

}

);

Console.WriteLine("list的长度为 : {0}",list.Count());

//多测试几次,就是说多运行几次

/*

* 从结构可以看出,我们的结构不是10000.这是为什么呢,这是因为List是费线程安全的

* ,也就是说,任何线程都可以修改他的值

*/

Console.ReadKey();

}

}

}

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

ConcurrentBag<int> list =new ConcurrentBag<int>();

Parallel.For(0, 10000, item =>

{

list.Add(item);

}

);

Console.WriteLine("ConcurrentBag的长度为 : {0}", list.Count());

//不管运行几次,结果都是10000

分析一下,因为ConcurrentBag是线程安全的,所以每次结果都是正确的.

下面我们来修改代码看看ConcurrentBag里面的数据到底是怎样存放的,修改代码如下:

using System;

using System.Collections.Concurrent;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace 并行集合和LINQ

{

class Program

{

static void Main(string[] args)

{

ConcurrentBag<int> list =new ConcurrentBag<int>();

Parallel.For(0, 10000, item =>

{

list.Add(item);

}

);

Console.WriteLine("ConcurrentBag的长度为 : {0}", list.Count());

//不管运行几次,结果都是10000

int n = 0;

foreach (var item in list)

{

if (n>10)

{

break;

}

n++;

Console.WriteLine("Item[{0}] = {1}",n,item);//,多运行几次,观察这里的输出

}

Console.WriteLine("ConcurrentBag的最大长度为 : {0}",list.Max());

Console.ReadKey();

}

}

}

分析:可以看到ConcurrentBag中的数据并不是按照顺序排列的,顺序是乱的,随机的.我们平时使用的Max,First,Last等LINQ方法都还有.其十分类似Enumerable的用法.

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

并行LINQ的用法和性能

1.AsParallel

案例:

using System;

using System.Collections.Concurrent;

using System.Collections.Generic;

using System.Diagnostics;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace 并行集合和LINQ

{

class Program

{

static void Main(string[] args)

{

Stopwatch sw = new Stopwatch();//需要添加命名空间 System.Threading.Tasks;

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);

Console.WriteLine("运行完毕");//这句话可能需要过一会才能出现

Console.ReadKey();

}

}

public class Custom

{

public string Name { get; set; }

public int Age { get; set; }

public string Address { get; set; }

}

}

分析:多运行即便可以发现,添加了AsParallel()方法的速度差不多快了一倍.其实,AsParallel()这个方法可以应用与任何集合,包括List<T>集合,从而提高查询速度和系统性能。

2.GroupBy方法

在项目中,我们经常要对数据做处理,比如分组统计,我们知道在LINQ中也可以实现,今天来学习以下新的ToLookUp方法,写一个测试方法:其他代码相似,只是测试代码不同

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);

Console.WriteLine("运行完毕");//这句话可能需要过一会才能出现

Console.ReadKey();

ToLookup方法是将集合转换成一个只读集合,所以在大数据量分组时性能优于List.

C#编程(六十三)----------并行LINQ的更多相关文章

  1. 四、并行编程 - 并行LINQ(PLINQ) 的使用。AsParallel

    用于对内存中的数据做并行运算,也就是说其只支持 LINQ to Object 的并行运算 一.AsParallel(并行化) 就是在集合后加个AsParallel(). 例如: , ); == ); ...

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

    5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 —— 第一天 认识Parallel 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq 5天玩转C#并行和多线程编 ...

  3. 孤荷凌寒自学python第六十三天学习mongoDB的基本操作并进行简单封装2

    孤荷凌寒自学python第六十三天学习mongoDB的基本操作并进行简单封装2 (完整学习过程屏幕记录视频地址在文末) 今天是学习mongoDB数据库的第九天. 今天继续学习mongoDB的简单操作, ...

  4. C#5.0之后推荐使用TPL(Task Parallel Libray 任务并行库) 和PLINQ(Parallel LINQ, 并行Linq). 其次是TAP(Task-based Asynchronous Pattern, 基于任务的异步模式)

    学习书籍: <C#本质论> 1--C#5.0之后推荐使用TPL(Task Parallel Libray 任务并行库) 和PLINQ(Parallel LINQ, 并行Linq). 其次是 ...

  5. 并行Linq(一)

    .Net 并行计算 ----并行Linq(一) 本文是.Net 并行计算 的第三篇 欢迎大家拍砖,阅读本文需要有LINQ基础,因为并行LINQ (PLinq) 其实是LINQ To Object 的并 ...

  6. JDBC编程六部曲

    今天初学jdbc,明白了大致的编程流程,在此总结一下: JDBC编程可以分为六步——六部曲: * 第一步:注册驱动. * 1.1 获取驱动对象 * 1.2 注册驱动 * 第二步:获取数据库连接 * 第 ...

  7. C# 多线程八之并行Linq(ParallelEnumerable)

    1.简介 关于并行Linq,Ms官方叫做并行语言集成(PLINQ)查询,其实本质就是Linq的多线程版本,常规的Linq是单线程的,也就是同步的过程处理完所有的查询.如果你的Linq查询足够简单,而且 ...

  8. 并行Linq

    有时候我们对大批量数据进行处理,此时并行linq就起作用了. 并行查询 对于以下查询可以耗时会非常大,如下: ; var r = new Random(); , arraySize).Select(x ...

  9. “全栈2019”Java第六十三章:接口与抽象方法详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

随机推荐

  1. 如何动态修改windows下的host文件

    事件背景:为了测试数据提交后,需要在另一个环境的多个测试节点下去验证测试数据是否添加成功,找了一大堆放法,用了比较笨的方法实现了.不多废话思路如下: 为了万无一失,先备份hosts文件内容: 1.读取 ...

  2. elasticsearch6.3.2之x-pack6.3.2破解安装并配合kibana使用

    原文链接:https://www.plaza4me.com/article/20180825223826278 由于在elasticsearch在6.3版本之后x-pack是默认安装好的,所以不再需要 ...

  3. 和为k的最长子数组及其延伸

    问题1: /** * 问题描述: * 给定一个无序数组arr,其中元素可正.可负.可0, * 求arr所有的子数组中正数与负数个数相等的最长子数组长度 * * 解题思路:对数组进行处理,正数为1,负数 ...

  4. C#数组 List、Dictionary 、Arrary、ArrayList

    #region Dictionary 泛型集合,动态修改查询.查询和排序 Dictionary<string, string> dic = new Dictionary<string ...

  5. git stash命令使用手册

    修改记录压栈保存: git stash push -u -m "msg" // -u ~ --意思是包含未被跟踪的文件git stash push -m "msg&quo ...

  6. hdu 1690 构图后Floyd 数据很大

    WA了好多次... 这题要用long long 而且INF要设大一点 Sample Input2 //T1 2 3 4 1 3 5 7 //L1-L4 C1-C4 距离和花费4 2 //结点数 询问次 ...

  7. 【LOJ】#2585. 「APIO2018」新家

    题解 成功把自己写自闭了 离散化之后再二分我是真不会算坐标啊我这个zz 先离散化所有坐标,然后对于每个位置维护一个最小前驱,然后线段树区间维护最小前驱 什么?位置一样?那就给每个大小为1的位置开个mu ...

  8. 001.Parted工具使用

    一 Parted简介 1.1 parted和fdisk 通常使用较多的磁盘管理工具为fdisk,但由于磁盘越来越廉价,且磁盘空间越来越大,而fdisk工具分区存在大小限制,只能划分小于2T的磁盘.因此 ...

  9. Web大前端面试题-Day4

    1. 如何实现瀑布流? 瀑布流布局的原理:1) 瀑布流布局要求要进行布置的元素等宽,   然后计算元素的宽度,   与浏览器宽度之比,得到需要布置的列数;2) 创建一个数组,长度为列数,   里面的值 ...

  10. python语法(四)— 文件操作

    前面几天学习了一写python的基础语法,也学习了分支if,循环while和for.由于之前已经做过几年的开发了,所以我们知道,许多数据来源并不是靠键盘输入到程序中去的,而是通过数据库和文件来获取到的 ...