天天看點

5天玩轉C#并行和多線程程式設計 —— 第二天 并行集合和PLinq

5天玩轉C#并行和多線程程式設計系列文章目錄

<a href="http://www.cnblogs.com/yunfeifei/p/3993401.html">5天玩轉C#并行和多線程程式設計 —— 第一天 認識Parallel</a>

<a href="http://www.cnblogs.com/yunfeifei/p/3998783.html">5天玩轉C#并行和多線程程式設計 —— 第二天 并行集合和PLinq</a>

<a href="http://www.cnblogs.com/yunfeifei/p/4106318.html">5天玩轉C#并行和多線程程式設計 —— 第三天 認識和使用Task</a>

<a href="http://www.cnblogs.com/yunfeifei/p/4111112.html">5天玩轉C#并行和多線程程式設計 —— 第四天 Task進階</a>

<a href="http://www.cnblogs.com/yunfeifei/p/4122084.html">5天玩轉C#并行和多線程程式設計 —— 第五天 多線程程式設計大總結</a>

  并行算法的出現,随之而産生的也就有了并行集合,及線程安全集合;微軟向的也算周到,沒有忘記linq,也推出了linq的并行版本,plinq - Parallel Linq.

 一、并行集合 —— 線程安全集合

  并行計算使用的多個線程同時進行計算,是以要控制每個線程對資源的通路,我們先來看一下平時常用的List&lt;T&gt;集合,在并行計算下的表現,建立一個控制台應用程式,添加一個PEnumerable類(當然你也直接寫到main方法裡面測試,建議分開寫),寫如下方法:

點選F5運作,得到如下結果:

5天玩轉C#并行和多線程程式設計 —— 第二天 并行集合和PLinq

看到結果中顯示的5851,但是我們循環的是10000次啊!怎麼結果不對呢?這是因為List&lt;T&gt;是非線程安全集合,意思就是說所有的線程都可以修改他的值。

下面我們來看下并行集合 —— 線程安全集合,在System.Collections.Concurrent命名空間中,首先來看一下ConcurrentBag&lt;T&gt;泛型集合,其用法和List&lt;T&gt;類似,先來寫個方法測試一下:

同時執行兩個方法,結果如下:

5天玩轉C#并行和多線程程式設計 —— 第二天 并行集合和PLinq

可以看到,ConcurrentBag集合的結果是正确的。下面我們修改代碼看看ConcurrentBag裡面的資料到底是怎麼存放的,修改代碼如下:

先來看一下運作結果:

5天玩轉C#并行和多線程程式設計 —— 第二天 并行集合和PLinq

可以看到,ConcurrentBag中的資料并不是按照順序排列的,順序是亂的,随機的。我們平時使用的Max、First、Last等linq方法都還有。其時分類似Enumerable的用法,大家可以參考微軟的MSDN了解它的具體用法。

關于線程安全的集合還有很多,和我們平時用的集合都差不多,比如類似Dictionary的ConcurrentDictionary,還有ConcurrentStack,ConcurrentQueue等。

 二、Parallel Linq的用法及性能

1、AsParallel

前面了解了并行的For和foreach,今天就來看一下Linq的并行版本是怎麼樣吧?為了測試,我們添加一個Custom類,代碼如下:

 寫如下測試代碼:

其實也就是加了一個AsParallel()方法,下面來看下運作結果:

5天玩轉C#并行和多線程程式設計 —— 第二天 并行集合和PLinq

時間相差了一倍,不過有時候不會相差這麼多,要看系統目前的資源使用率。大家可以多測試一下。

其實,AsParallel()這個方法可以應用與任何集合,包括List&lt;T&gt;集合,進而提高查詢速度和系統性能。

2、GroupBy方法

在項目中,我們經常要對資料做處理,比如分組統計,我們知道在linq中也可以實作,今天來學習一下新的ToLookup方法,寫一個測試方法,代碼如下:

運作結果如下:

5天玩轉C#并行和多線程程式設計 —— 第二天 并行集合和PLinq

ToLookup方法是将集合轉換成一個隻讀集合,是以在大資料量分組時性能優于List.大家可以查閱相關資料,這裡由于篇幅問題,不再細說。

繼續閱讀