多線程之旅(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
  • 概述:本文代碼示例演示瞭如何在WPF中使用LiveCharts庫創建動態條形圖。通過創建數據模型、ViewModel和在XAML中使用`CartesianChart`控制項,你可以輕鬆實現圖表的數據綁定和動態更新。我將通過清晰的步驟指南包括詳細的中文註釋,幫助你快速理解並應用這一功能。 先上效果: 在 ...
  • openGauss(GaussDB ) openGauss是一款全面友好開放,攜手伙伴共同打造的企業級開源關係型資料庫。openGauss採用木蘭寬鬆許可證v2發行,提供面向多核架構的極致性能、全鏈路的業務、數據安全、基於AI的調優和高效運維的能力。openGauss深度融合華為在資料庫領域多年的研 ...
  • openGauss(GaussDB ) openGauss是一款全面友好開放,攜手伙伴共同打造的企業級開源關係型資料庫。openGauss採用木蘭寬鬆許可證v2發行,提供面向多核架構的極致性能、全鏈路的業務、數據安全、基於AI的調優和高效運維的能力。openGauss深度融合華為在資料庫領域多年的研 ...
  • 概述:本示例演示了在WPF應用程式中實現多語言支持的詳細步驟。通過資源字典和數據綁定,以及使用語言管理器類,應用程式能夠在運行時動態切換語言。這種方法使得多語言支持更加靈活,便於維護,同時提供清晰的代碼結構。 在WPF中實現多語言的一種常見方法是使用資源字典和數據綁定。以下是一個詳細的步驟和示例源代 ...
  • 描述(做一個簡單的記錄): 事件(event)的本質是一個委托;(聲明一個事件: public event TestDelegate eventTest;) 委托(delegate)可以理解為一個符合某種簽名的方法類型;比如:TestDelegate委托的返回數據類型為string,參數為 int和 ...
  • 1、AOT適合場景 Aot適合工具類型的項目使用,優點禁止反編 ,第一次啟動快,業務型項目或者反射多的項目不適合用AOT AOT更新記錄: 實實在在經過實踐的AOT ORM 5.1.4.117 +支持AOT 5.1.4.123 +支持CodeFirst和非同步方法 5.1.4.129-preview1 ...
  • 總說周知,UWP 是運行在沙盒裡面的,所有許可權都有嚴格限制,和沙盒外交互也需要特殊的通道,所以從根本杜絕了 UWP 毒瘤的存在。但是實際上 UWP 只是一個應用模型,本身是沒有什麼許可權管理的,許可權管理全靠 App Container 沙盒控制,如果我們脫離了這個沙盒,UWP 就會放飛自我了。那麼有沒... ...
  • 目錄條款17:讓介面容易被正確使用,不易被誤用(Make interfaces easy to use correctly and hard to use incorrectly)限制類型和值規定能做和不能做的事提供行為一致的介面條款19:設計class猶如設計type(Treat class de ...
  • title: 從零開始:Django項目的創建與配置指南 date: 2024/5/2 18:29:33 updated: 2024/5/2 18:29:33 categories: 後端開發 tags: Django WebDev Python ORM Security Deployment Op ...
  • 1、BOM對象 BOM:Broswer object model,即瀏覽器提供我們開發者在javascript用於操作瀏覽器的對象。 1.1、window對象 視窗方法 // BOM Browser object model 瀏覽器對象模型 // js中最大的一個對象.整個瀏覽器視窗出現的所有東西都 ...