C#中的并發(fā)集合Concurrent類
一、概述:
System.Collections.Concurrent 命名空間提供多個線程安全集合類。
當有多個線程并發(fā)訪問集合時,應(yīng)使用這些類代替 System.Collections 和 System.Collections.Generic 命名空間中的對應(yīng)類型。
為了對集合進行線程安全的訪問,定義了 IProducerConsumerCollection接口。這個接口中最重 要的方法是TryAdd()和TryTake()。
- TryAdd()方法嘗試給集合添加一項,但如果集合禁止添加項,這個操作就可能失敗。為了給出相關(guān)信息,TryAdd()方法返回一個布爾值,以說明操作是成功還是失敗。
- TryTake()方法也以這種方式工作,以通知調(diào)用者操作是成功還是失敗,并在操作成功時返回集合中的項。
二、空間中包含的類
ConcurrentXXX :這些集合是線程安全的,如果某個動作不適用于線程的當前狀態(tài),它們就返回false。在繼續(xù)之前,總是霈要確認添加或提取元素是否成功。不能相信集合會完成任務(wù)。
1、ConcurrentQueue 隊列
這個集合類用一種免鎖定的算法實現(xiàn),使用在內(nèi)部合并到一個鏈表中的32項數(shù)組。
訪問隊列元素的方法有Enqueue()、TryDequeue()和TryPeek()。這些方法的命名非常類似于前面Queue類的方法,只是給可能調(diào)用失敗的方法加上了前綴Try。
因為這個類實現(xiàn)了IProducerConsumerCollection接口,所以 TryAdd()和 TryTake()方法僅調(diào)用 Enqueue()和 TryDequeue()方法。
2、ConcurrentStack 堆棧
非常類似于ConcurrentQueue類,只是帶有另外的元素訪問方法。
ConcurrcntStack類定義了 Push()、PushRange()、TryPeek()、TiyPop()和 TryPopRange() 方法。在內(nèi)部這個類使用其元素的鏈表。
3、ConcurrentBag 包
該類沒有定義添加或提取項的任何順序。這個類使用一個把線程映射到內(nèi)部使用的數(shù)組上的概念,因此嘗試減少鎖定。
訪問元素的方法有Add()、TryPeek()和 TryTake()。
4、ConcurrentDictionary 字典
——這是一個線程安全的鍵值集合。
TryAdd()、TryGetValue()、TryRemove()和TryUpdate()方法以非阻塞的方式訪問成員。
因為元素基于鍵和值, 所以 ConcurrentDictionary沒有實現(xiàn) IProducerConsumerCollection。
5、BlockingCollection 集合
這個集合在可以添加或提取元素之前,會阻塞線程并一直等待。
BlockingCollection集合提供了一個接口,以使用Add()和Take()方法來添加和刪除元素。 這些方法會阻寒線程,一直等到任務(wù)可以執(zhí)行為止。
Add()方法有一個重載版本,其中可以給該重載版本傳遞一個CancellationToken令牌。
這個令牌允許取消被阻塞的調(diào)用。如果不希望線程無限期地等待下去,且不希望從外部取消調(diào)用,就可以使用TryAdd()和 TryTake()方法,在這些方法中,也可以指定一個超時值,它表示在調(diào)用失敗之前應(yīng)阻塞線程和等待的最長時間。
6、BlockingCollection 阻塞式集合
這是對實現(xiàn)了 IProducerConsumerCollection接口的任意類的修飾器,它默認使用ConcurrentQueue類。
還可以給構(gòu)造函數(shù)傳遞任何其他實現(xiàn)了 IProducerConsumerCollection 接口的類。
下面的代碼示例簡單演示了使用BlockingCollection類和多個線程的過程。
一個線程是生成器,它使用Add()方法給集合寫入元素,另一個線程是使用者,它使用Take()方法從集合中提取元素:
internal static BlockingCollection<int> _TestBCollection; class ThreadWork1 // 生產(chǎn)者 { public ThreadWork1() { } public void run() { System.Console.WriteLine("ThreadWork1 run { "); for (int i = 0; i < 100; i++) { System.Console.WriteLine("ThreadWork1 producer: " + i); _TestBCollection.Add(i); } _TestBCollection.CompleteAdding(); System.Console.WriteLine("ThreadWork1 run } "); } } class ThreadWork2 // 消費者 { public ThreadWork2() { } public void run() { int i = 0; int nCnt = 0; bool IsDequeuue = false; System.Console.WriteLine("ThreadWork2 run { "); while (!_TestBCollection.IsCompleted) { IsDequeuue = _TestBCollection.TryTake(out i); if (IsDequeuue) { System.Console.WriteLine("ThreadWork2 consumer: " + i * i + " =====" + i); nCnt++; } } System.Console.WriteLine("ThreadWork2 run } "); } } static void StartT1() { ThreadWork1 work1 = new ThreadWork1(); work1.run(); } static void StartT2() { ThreadWork2 work2 = new ThreadWork2(); work2.run(); } static void Main(string[] args) { Task t1 = new Task(() => StartT1()); Task t2 = new Task(() => StartT2()); _TestBCollection = new BlockingCollection<int>();//可以跟容量 Console.WriteLine("Sample 4-4 Main {"); Console.WriteLine("Main t1 t2 started {"); t1.Start(); t2.Start(); Console.WriteLine("Main t1 t2 started }"); Console.WriteLine("Main wait t1 t2 end {"); Task.WaitAll(t1, t2); Console.WriteLine("Main wait t1 t2 end }"); Console.WriteLine("Sample 4-4 Main }"); }
到此這篇關(guān)于C#并發(fā)集合Concurrent類的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
WinForm使用DecExpress控件中的ChartControl插件繪制圖表
這篇文章介紹了WinForm使用DecExpress控件中的ChartControl插件繪制圖表的方法,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-05-05C#實現(xiàn)壓縮和解壓縮的方法示例【Gzip和Zip方式】
這篇文章主要介紹了C#實現(xiàn)壓縮和解壓縮的方法,結(jié)合具體實例形式分析了Gzip和Zip兩種壓縮操作實現(xiàn)方法,需要的朋友可以參考下2017-06-06C#5.0中的異步編程關(guān)鍵字async和await
這篇文章介紹了C#5.0中的異步編程關(guān)鍵字async和await,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-06-06C#根據(jù)前臺傳入實體名稱實現(xiàn)動態(tài)查詢數(shù)據(jù)
這篇文章主要為大家詳細介紹了C#如何根據(jù)前臺傳入實體名稱實現(xiàn)動態(tài)查詢數(shù)據(jù)的功能,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下2023-04-04C#中實現(xiàn)判斷某個類是否實現(xiàn)了某個接口
這篇文章主要介紹了C#中實現(xiàn)判斷某個類是否實現(xiàn)了某個接口,本文給出了多種判斷方法,需要的朋友可以參考下2015-06-06