.NET多線程知識快速學習

多線程是一個不會過期的話題,由於每一個開發的成長必然要掌握這個知識點,不然半懂不懂怎麼保證系統的可靠性和性能,其實在網上隨便一搜都會有海量的文章說這個話題,大多數寫得很細寫得很是好,但發現不多有概覽性的文章,我但願能借本文給你們一個全局視野,結合多年實踐幫你們快速學習或者回顧思考,對感興趣的知識點再深刻學習瞭解。多線程

1、知識點歸納性能

2、具體實例演示如何實現學習

> Thread 多線程最基礎的類字體

//ThreadPool.GetMaxThreads(out int maxTCount, out int maxPCount);
//ThreadPool.GetMinThreads(out int minTCount, out int minPCount);
//ThreadPool.SetMaxThreads(maxTCount, maxPCount);// 調整最大線程數
//ThreadPool.SetMinThreads(minTCount, minPCount);// 調整最小線程數

long tick = C_ITEM_COUNT;
ManualResetEvent signal = new ManualResetEvent(false);
Console.WriteLine("========== 示例:採用Thread執行處理 ==========");
for (int i = 0; i < C_ITEM_COUNT; i++)
{
    new Thread((obj) =>
    {
        Thread.Sleep(500);
        Console.Write(" {0} ", obj);
        if (Interlocked.Decrement(ref tick) == 0)
            signal.Set();
    }).Start(i);
}
Console.Write(" 等待子線程執行 ");
signal.WaitOne();
Console.WriteLine();
Console.WriteLine("所有線程執行完畢,按任意鍵繼續...");

> ThreadPool 線程池,XX池的概念能夠普遍應用於其餘資源管理,例如字體池(防句柄泄露)、短信貓池等等spa

tick = C_ITEM_COUNT;
signal.Reset();
Console.WriteLine();
Console.WriteLine("========== 示例:採用ThreadPool執行處理 ==========");
for (int i = 0; i < C_ITEM_COUNT; i++)
{
    ThreadPool.QueueUserWorkItem((obj) =>
    {
        Thread.Sleep(500);
        Console.Write(" {0} ", obj);
        if (Interlocked.Decrement(ref tick) == 0)
            signal.Set();
    }, i);
}
Console.Write(" 等待子線程執行 ");
signal.WaitOne();
Console.WriteLine();
Console.WriteLine("所有線程執行完畢,按任意鍵繼續...");

> Task 任務,功能豐富用法靈活。結合現實生活用字面意思去理解就好:能夠同時作多個任務,任務作完能夠接着作其餘任務,任務可能會取消等等。線程

tick = C_ITEM_COUNT;
signal.Reset();
Console.WriteLine();
Console.WriteLine("========== 示例:採用Task執行處理,注意取消了處理{0}的進程 ==========", C_ITEM_COUNT - 2);
var tasks = new Tuple<Task, CancellationTokenSource>[C_ITEM_COUNT];
for (int i = 0; i < C_ITEM_COUNT; i++)
{
    var cts = new CancellationTokenSource();
    var task = Task.Factory.StartNew((obj) =>
    {
        Thread.Sleep(500);
        Console.Write(" {0} ", obj);
    }, i, cts.Token);
    task.ContinueWith((t) =>
    {
        if (Interlocked.Decrement(ref tick) == 0)
            signal.Set();
    });
    tasks[i] = new Tuple<Task, CancellationTokenSource>(task, cts);
}

tasks[C_ITEM_COUNT - 2].Item2.Cancel();// 取消線程。

Console.Write(" 等待子線程執行 ");
signal.WaitOne();
Console.WriteLine();
Console.WriteLine("所有線程執行完畢,按任意鍵繼續...");

> Parallel 並行3d

tick = C_ITEM_COUNT;
signal.Reset();
Console.WriteLine();
Console.WriteLine("========== 示例:採用Parallel執行處理 ==========");
Parallel.For(0, C_ITEM_COUNT, obj =>
{
    Thread.Sleep(500);
    Console.Write(" {0} ", obj);
    if (Interlocked.Decrement(ref tick) == 0)
        signal.Set();
});

Console.Write(" 等待子線程執行 ");
signal.WaitOne();
Console.WriteLine();
Console.WriteLine("所有線程執行完畢,按任意鍵繼續...");

以上示例執行結果以下,重點能夠關注下"等待子線程執行"這個節點,理解主線程和各子線程的優先執行順序code

3、性能對比(理解線程池技術的性能也能夠經過最大最小線程數調節)blog

> 循環數:200,線程池參數:默認進程

> 循環數:200,線程池參數:50 - 1000

> 循環數200,線程池參數:100-1000

 

> 循環數200,線程池參數:200-1000

 

最大線程數 ~ 最小線程數 Thread(ms) ThreadPool(ms) Task(ms) Parallel(ms)
2047/1000 ~ 12/12 2712.09 8057.14 8585.01 7526.57
1000/1000 ~ 50/50 2733.25 2289.96 2218.29 3660.33
1000/1000 ~ 100/100 2503.08 1620.73 1534.50 1742.78
1000/1000 ~ 200/200 2999.27 1436.24 1150.21 935.22

 4、結論

> Thread就像脫繮的野馬,不受控制,建立多少就運行多少,可能少許時效率是高了,量大的時候除了性能沒優點,還可能致使句柄泄露。

> ThreadPool與Task相似,但Task相比效率更高用法更靈活。

> Parallel自帶了同步功能,不須要用信號量來作額外的同步等待。

> ThreadPool、Task、Parallel的性能都取決於線程池最大線程數和最小線程數。

> 推薦使用 Task 和 Parallel,具體用哪一個能夠參考用法本身斟酌。

相關文章
相關標籤/搜索