多線程之旅(ThreadPool 線程池)

来源:https://www.cnblogs.com/chenxi001/archive/2020/03/30/12601713.html
-Advertisement-
Play Games

一、什麼是ThreadPool 線程池(源碼) 1.線程池顧名思義,有我們的系統創建一個容器裝載著我們的線程,由CLR控制的所有AppDomain共用。線程池可用於執行任務、發送工作項、處理非同步 I/O、代表其他線程等待以及處理計時器。所以使用線程池不需要自己創建線程,而是通過線程池來創建和執行和管 ...


一、什麼是ThreadPool 線程池(源碼

      1.線程池顧名思義,有我們的系統創建一個容器裝載著我們的線程,由CLR控制的所有AppDomain共用。線程池可用於執行任務、發送工作項、處理非同步 I/O、代表其他線程等待以及處理計時器。所以使用線程池不需要自己創建線程,而是通過線程池來創建和執行和管理線程。

二、ThreadPool 線程池和線程的區別

      1.ThreadPool 線程池是在.NET 2.0出現的,是一個享元模式整個程式共同享用這一個線程池,當我們的線程執行任務之後它不會立刻銷毀,它會回到線程池中,如果有新的任務它就會去執行。避免了我們線程的重覆創建和銷毀(也不會造成我們CPU的上下文切換的損耗)。

      2.大家仔細看一下我前面寫的Thread 創建線程執行任務之後,它會自動銷毀。那問題來了我們經常的創建、銷毀線程這可都是資源的浪費呀!!所以我們要利用每個線程占有的資源。

三、ThreadPool 線程池缺點

       1.線程池在性能上優於線程,但是它也是有缺點的。它不支持線程的取消、完成、失敗通知等交互性操作。

       2.它不能設置池中線程的Name,會增加使用者的難度。

  3.線程池中線程通常都是後臺線程,優先順序為ThreadPriority.Normal

  4.線程池堵塞會影響我們的性能,阻塞會使CLR錯誤地認為它占用了大量CPU。CLR能夠檢測或補償(往池中註入更多線程),但是這可能使線程池受到後續超負荷的印象。Task (也及時後面要講的)解決了這個問題。

  5.線程池使用的是全局隊列,全局隊列中的線程依舊會存在競爭共用資源的情況,從而影響性能(Task 解決了這個問題,方案是使用本地隊列)。

四、線程池工作原理

  1.CLR初始化時,線程池中是沒有線程的,但是內部有一個操作請求隊列,當我們的應用程式使用非同步時,會將一個記錄項添加到線程池的隊列中,線程池隊列會自動讀取這個記錄項,並且發給一個線程池的線程,如果線程池沒有線程就會創建一個線程執行這任務,當線程完成任務它不會自動銷毀而是回到我們的線程池中,等待線程池派發新的任務。

  2.如果程式給線程池派發了很多任務,線程池也會使用這一個線程執行所有的任務,如果我們的請求速度大於了我們的線程處理速度,就會創建額外線程,就不會導致我們創建了過多的線程。

  2.當我們的線程有大量休息的,它們會在一段時間內自動銷毀。這樣很好的控制了我們應用程式的性能。

五、ThreadPool 線程池使用

  1.ThreadPool是一個靜態類,調用QueueUserWorkItem方法,是可以將一個非同步計算放入我們的線程池隊列中。

public static bool QueueUserWorkItem(WaitCallback callBack);
public static bool QueueUserWorkItem(WaitCallback callBack, object state);
方法 說明
QueueUserWorkItem 啟動線程池裡的一個線程(工作者線程)
GetMinThreads 檢索線程池在新請求預測中能夠按需創建的線程的最小數量。
GetMaxThreads 最多可用線程數,所有大於此數目的請求將保持排隊狀態,直到線程池線程由空閑。
GetAvailableThreads 剩餘空閑線程數。
SetMaxThreads 設置線程池中的最大線程數(請求數超過此值則進入隊列)。
SetMinThreads 設置線程池最少需要保留的線程數。

 

 

 

 

 

 

  2.我們可以看到ThreadPool比Thread少了很多的API,被砍掉了

/// <summary>
        /// ThreadPool的使用
        /// workerThreads  CLR線程池分為工作者線程(workerThreads)
        /// completionPortThreads I/O線程(completionPortThreads)
        /// </summary>
        public static void Show()
        {
            //使用線程
            ThreadPool.QueueUserWorkItem((x) => Running());
            ThreadPool.GetAvailableThreads(out int workerThreads, out int completionPortThreads);
            Console.WriteLine($"沒有設置線程數之前 workerThreads:{workerThreads}  completionPortThreads:{completionPortThreads}");
            //設置最大的線程數
            ThreadPool.SetMaxThreads(16, 16);
            //設置最小的線程數
            ThreadPool.SetMinThreads(8, 8);
            ThreadPool.GetAvailableThreads(out int workerThreads1, out int completionPortThreads1);
            Console.WriteLine($"設置最大的線程數之後 workerThreads:{workerThreads1}  completionPortThreads:{completionPortThreads1}");
            Console.ReadLine();
        }
View Code

   3.我們要註意的就是堵塞線程的時候一定要做好處理,最好是不要堵塞我們的線程,不然很容易造成死鎖GG

        /// <summary>
        /// ThreadPool 線程等待
        ///類  包含了一個bool屬性
        ///false--WaitOne等待--Set--true--WaitOne直接過去
        ///true--WaitOne直接過去--ReSet--false--WaitOne等待
        ///https://www.cnblogs.com/howtrace/p/11362284.html
        /// </summary>
        public static void Show1()
        {
            //設置最大的線程數
            ThreadPool.SetMaxThreads(16, 16);
            //設置最小的線程數
            ThreadPool.SetMinThreads(8, 8);
            //設置false使用WaitOne()會直接堵塞線程,不會釋放 、Set()設置為true
            ManualResetEvent manualResetEvent = new ManualResetEvent(false);
            //設置false使用WaitOne()會直接堵塞線程,不會釋放 、Set()設置為true
            AutoResetEvent autoResetEvent = new AutoResetEvent(false);
            //上面兩種方法都是可以攔截線程,都是繼承EventWaitHandle 介面
            //就都具有Reset() //紅燈 設置為false導致線程等待
            //Set() //綠燈 設置為true 啟動線程繼續執行
            //WaitOne() // 等待信號 會根據我們線程狀態執行,為true不需要等待直接執行
            //反之為false會等待線程狀態為true才會執行

            //不同點 ManualResetEvent AutoResetEvent
            //ManualResetEvent 在·使用Set()的時候會所有處理 WaitOne 狀態線程均繼續執行。
            //AutoResetEvent 在使用Set()的時候會執行一個線程其他的線程繼續等待執行。

            for (int i = 0; i < 20; i++)
            {
                var k = i;
                ThreadPool.QueueUserWorkItem(x =>
                {
                    Console.WriteLine(k);
                    if (k < 18)
                    {
                        //等待線程,但是上面我們只開了16個線程,結果我18個線程全部等待
                        //導致了死鎖
                        manualResetEvent.WaitOne();
                    }
                    else
                    {
                        //恢復執行狀態
                        manualResetEvent.Set();
                    }
                });
                if (manualResetEvent.WaitOne())
                {
                    Console.WriteLine("沒有死鎖、、、");
                }
                Console.WriteLine("等著QueueUserWorkItem完成後才執行");
            }
            Console.ReadLine();
        }
View Code
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 需求分析 在分享源碼之前,先將b2b2c系統中許可權模塊的需求整理、明確,方便源碼的理解。 業務需求 b2b2c電子商務系統中許可權主要有三個角色:買家、賣家、平臺管理員。 其中賣家角色中又有店員,可以設置店員管理不同的許可權(如商品和訂單的許可權分派給不同的店員),同理平臺管理員也需要進行上述精細許可權的管 ...
  • 一、無監督學習基礎知識 利用無標簽的數據學習數據的分佈或數據與數據之間的關係被稱作無監督學習 有監督學習和無監督學習的最大區別在於數據是否有標簽 無監督學習最常應用的場景是聚類(Clustering)和降維(Dimension Reduction) 二、聚類 聚類是根據數據的“相似性”將數據分為多類 ...
  • 有的人說 Python 入門容易,但是精通難的語言,這點我非常贊同。 Python 語言里有許多(而且是越來越多)的高級特性,是 Python 發燒友們非常喜歡的。在這些人的眼裡,能夠寫出那些一般開發者看不懂的高級特性,就是高手,就是大神。 但你要知道,在團隊合作里,炫技是大忌。 為什麼這麼說呢?我 ...
  • 目錄 在日常開發中,對數據進行序列化和反序列化,是常備的操作。而在Python標準庫中提供了json模塊對JSON數據的處理功能。 什麼是json? JSON(JavaScript Object Notation)是一種使用廣泛的輕量數據格式,相對於XML而言更簡單,也易於閱讀和編寫,機器也方便解析 ...
  • 前言 Python爬蟲要經歷爬蟲、爬蟲被限制、爬蟲反限制的過程。當然後續還要網頁爬蟲限制優化,爬蟲再反限制的一系列道高一尺魔高一丈的過程。爬蟲的初級階段,添加headers和ip代理可以解決很多問題。 PS:如有需要Python學習資料的小伙伴可以加點擊下方鏈接自行獲取http://t.cn/A6Z ...
  • a>使用的軟體是vs2017和sqlServer2012,使用的ASP.NET控制項是sqlDataSource、dropDownlist和UpdatePanel. b>打開sqlServer,以window身份驗證登錄,建立省份表與市區表,如圖1.1和圖1.2 圖1.1 省份表 圖1.2 市區表 c ...
  • 前言 AutoWrapper是一個簡單可自定義全局異常處理程式和ASP.NET Core API響應的包裝。他使用ASP.NET Core middleware攔截傳入的HTTP請求,並將最後的結果使用統一的格式來自動包裝起來.目的主要是讓我們更多的關註業務特定的代碼要求,並讓包裝器自動處理HTTP ...
  • ViewComponent的一種使用方法 最近在一個自己新建的Core項目中想使用Html.Action(),突然發現這個方法已經沒了,下麵我按照官網(https://docs.microsoft.com/zh cn/aspnet/core/mvc/views/view components?vie ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...