C#并行和多线程编程

时间:2022-09-28 23:53:03

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

 

5天玩转C#并行和多线程编程系列文章目录

5天玩转C#并行和多线程编程 —— 第一天 认识Parallel

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

5天玩转C#并行和多线程编程 —— 第三天 认识和使用Task

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

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

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

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

C#并行和多线程编程

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

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

C#并行和多线程编程
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());
}
C#并行和多线程编程

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

C#并行和多线程编程

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

C#并行和多线程编程
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()); }
C#并行和多线程编程

先来看一下运行结果:

C#并行和多线程编程

可以看到,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; }
}

写如下测试代码:

C#并行和多线程编程
 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);
}
C#并行和多线程编程

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

C#并行和多线程编程

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

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

2、GroupBy方法

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

C#并行和多线程编程
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);
}
C#并行和多线程编程

运行结果如下:

C#并行和多线程编程

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

 
分类: C#

C#并行和多线程编程的更多相关文章

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

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

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

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

  3. 5天玩转C&num;并行和多线程编程 —— 第三天 认识和使用Task

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

  4. 5天玩转C&num;并行和多线程编程 —— 第二天 并行集合和PLinq

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

  5. 5天玩转C&num;并行和多线程编程 —— 第一天 认识Parallel

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

  6. 5天玩转C&num;并行和多线程编程

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

  7. 5天玩转C&num;并行和多线程编程 —— 第一天 认识Parallel 转载 https&colon;&sol;&sol;www&period;cnblogs&period;com&sol;yunfeifei&sol;p&sol;3993401&period;html

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

  8. C&num;并行和多线程编程&lowbar;&lpar;1&rpar;认识Parallel

    Parallel: 英 [ˈpærəlel]    美 [ˈpærəˌlɛl] ,并联的,并行的. 随着多核时代的到来,并行开发越来越展示出它的强大威力!使用并行程序,充分的利用系统资源,提高程序的性 ...

  9. python 常见错误和异常 函数 正则表达式及多线程编程

    生成随机密码#!/usr/bin/env python import stringfrom random import choice def gen_pass(num=9): all_chs = st ...

随机推荐

  1. JS简介

    JS是一本广泛应用于浏览器客户端的脚本语言,由netspace公司设计,当时和sun公司合作,所以名字取得像java JS的常见用途:1)HTML DOM操作(节点操作,比如添加.修改.删除节点 ) ...

  2. Oracle执行语句跟踪&lpar;2&rpar;——使用10046事件实现语句追踪

    接上篇博文Oracle执行语句跟踪(1)--使用sql trace实现语句追踪,一旦我们通过会话追踪获取到超时事物的执行语句,就可以使用10046事件对语句进行追踪. 启用10046事件追踪的方式 S ...

  3. &period;NET下文本相似度算法余弦定理和SimHash浅析及应用

    余弦相似性 原理:首先我们先把两段文本分词,列出来所有单词,其次我们计算每个词语的词频,最后把词语转换为向量,这样我们就只需要计算两个向量的相似程度.   我们简单表述如下   文本1:我/爱/北京/ ...

  4. Qt---自定义界面之QStyle

    最近想学习下Qt的自定义界面,因此花了点时间看了下QStyle,,,,结果很难受,这一块涉及到一大块GUI的具体实现方式,看得我很头疼.想看第一手资料并且英语功底不错的可以直接上qt文档,下面我会以易 ...

  5. Centos7-卸载自带的jdk 安装jdk8

    卸载JDK Centos7一般都会带有自己的openjdk,我们一般都回用oracle的jdk,所以要卸载 步骤一:查询系统是否以安装jdk #rpm -qa|grep java 或    #rpm ...

  6. 在django中,redirect如何传递message。

    众所周知,在django中,默认的message,只能在同一个request中传递. 但如果在请求过程中,使用了redirect跳转,那么,这个一次性的message就会失败, 无法在前端给用户提示. ...

  7. Javascript玩转继承&lpar;一&rpar;

    Javascript究竟是一门面向对象的语言,还是一门支持对象的语言,我想每个人都有着自己的看法.那些Javascript忠实的Fans一定讲Javascript是一门面向对象的语言,像<Jav ...

  8. 优秀 H5 案例收集 vol&period;4(不定期更新)

    重返木叶村 http://hyrz.qq.com/act/a20160113muyecun/index.html 飞越淘宝奇市 https://g.alicdn.com/fdilab/flyover- ...

  9. &period;netcore 与 Docker

    CentOS下Docker与.netcore(一) 之 安装 CentOS下Docker与.netcore(二) 之 Dockerfile CentOS下Docker与.netcore(三)之 三剑客 ...

  10. 如何在 Linux 虚拟机上扩展根文件系统

    问题描述 通过 Azure 平台部署的 Linux 虚拟机默认的根文件系统容量有限,需要进行扩展. 问题分析 由于 Azure 平台部署的 Linux 虚拟机默认根文件系统容量比较小,客户在使用过程中 ...