接上文 多執行緒程式設計學習筆記——使用併發集合(一)
接上文 多執行緒程式設計學習筆記——使用併發集合(二)
四、 使用concurrentbag建立乙個可擴充套件的爬蟲
本示例在多個獨立的即可生產任務又可消費任務的工作者間如何擴充套件工作量。
1.程式**如下。
using2.程式執行結果,如下圖。system;
using
system.collections.generic;
using
system.linq;
using
system.text;
using
system.threading.tasks;
using
system.collections.concurrent;
using
system.diagnostics;
using
system.threading;
namespace
threadcollectiondemo
static
async
task runbag()
;var crawlers = new task[5
];
for (int i = 1; i <= 5; i++)
);crawlers[i - 1] = task.run(() =>craw(taskbag,crawlername));
}await
task.whenall(crawlers);
}static
async task craw(concurrentbagbag, string
crawlername)
url 從concurrentbag 取出,上一節點,名稱
", task.urltocraw, task.productname, crawlername);
ienumerable
urls = await
getlinksfromcontent(task);
if (urls != null
) ;
bag.add(t);
} }}
if (task != null
) 個url 新增到concurrentbag,執行緒名稱,爬蟲名稱
", task.urltocraw, task.productname, crawlername);
}else
console.writeline(
"task is null ");
}
static
async taskstring>>getlinksfromcontent(crawlingtask task)
static
void
createlinks()
;
contextitems[
""] = new
; contextitems[
""] = new
; contextitems[
""] = new
; contextitems[
""] = new
; }
static
task getrandomdely()
}
class
crawlingtask
public
string productname }}
這個程式模擬了使用多個網路爬蟲進行網頁索引的場景。剛開始,我們定義了乙個包含網頁url的字典。這個字典模擬了包含其他頁面鏈結的網頁。這個實現非常簡單,並不關心索引已經訪問過的頁面,但正因為它如此簡單,我們才可能關注並行工作負載。
接著建立了乙個並發包,其中包含爬蟲任務。我們建立了四個爬蟲,並且給每個爬蟲都提供了乙個不同的**根url。然後等等所有爬蟲完成工作。現在每個爬蟲開始檢查提供給它的**url。我們通過等待乙個隨機事件來模擬網路io處理。如果頁面包含的url越多,爬蟲向包中放入的任務也越多。然後檢查包中是否還有任何需要爬蟲處理的任務,如果沒有說明爬蟲完成了工作 。
如果檢查前四個根url後的第一行輸出,我們將看到爬蟲n放置的任務通過會被同乙個爬蟲處理。然而,接下來的行則會不同。這是因為concurrentbag內部針對多個執行緒既可以新增元素又可以刪除元素的場景進行了優化。實現方式是每個執行緒使用自己的本地佇列的元素,所以使用這個佇列時無需要任何鎖。只有當本地佇列中沒有任何元素時,我們才執行一些鎖定操作並嘗試從其他執行緒的本地佇列中「偷取」工作。這種行為 有豕於在所有工作 者間分發工作並避免使用鎖。
五、 使用blockingcollention進行非同步處理
本示例學習如何使用blockingcollection來簡化實現 非同步處理的工作負載。
1.程式**如下。
using2.程式執行結果,如下圖。system;
using
system.collections.generic;
using
system.linq;
using
system.text;
using
system.threading.tasks;
using
system.collections.concurrent;
using
system.diagnostics;
using
system.threading;
namespace
threadcollectiondemo
static
async task runblock(iproducerconsumercollectioncollection = null
)
var tasksrc = task.run(() =>taskproduct(taskblock));
task process = new task[4
];
for (int i = 1; i <= 4; i++)
await
tasksrc;
await
task.whenall(process);
} static
async task taskproduct(blockingcollectionblock)
;block.add(workitem);
console.writeline(
string.format("
把 元素新增到blockingcollection
", workitem.id));
}block.completeadding();
}static
async task taskprocess(blockingcollectioncollection, string
name)
處理 操作 名稱: ---
",item.id,name));
await
getrandomdely();}}
static
task getrandomdely()} }
先說第乙個場景,這裡我們使用了blockingcollection類,它帶來了很多優勢。首先,我們能夠改變任務儲存在阻塞集合中的方式。預設情況下它使用的是concurrentqueue容器,但是我們能夠使用任何實現 iproducerconsumerconllection泛型介面的集合。
工作者通過對阻塞集合迭代呼叫getconsumingenumerable方法來獲取 工作項。如果在這個集合中沒有任何元素,迭代器會阻塞工作執行緒直到有元素被放到集合中。當生產才呼叫集合的completedding時迭代週期會結束。這標誌著工作完成。
工作量生產者將任務插入到blockingcollection,然後呼叫 completeadding方法,這會使用所有工作 者完成工作 。現在在程式輸出中我們看到兩個結果序列,演示了併發佇列和堆疊集合的不同之處。
多執行緒(併發)學習筆記
1,無論以哪種方式啟動乙個執行緒,要給執行緒乙個名字,對排錯 監控有幫助。2,要對執行緒interrupt做處理。3,futrure 是任務的提交者和執行者之間的通訊手段,get 會阻塞 executorservice executor executors.newsinglethreadexecut...
多執行緒高併發程式設計學習筆記三
高併發程式設計學習筆記三 併發容器 佇列 1.map set的選擇使用 1.不需要執行緒安全 hashmap 無序的key value 1.建立table來儲存entry 2.hashcode key 得到鍵值對應該存放的位置 3.用equal方法比較key,如果相同覆蓋資料,如果不同接到下面形成鍊...
多執行緒併發程式設計
docker 可謂是開啟了容器化技術的新時代,現在無論大中小公司基本上都對容器化技術有不同程度的嘗試,或是已經進行了大量容器化的改造。伴隨著 kubernetes 和 cloud native 等技術和理念的普及,也大大增加了業務容器化需求。而這一切的推進,不可避免的技術之一便是構建容器映象。在本場...