C# ThreadPool類(線程池)

地址:https://www.cnblogs.com/scmail81/archive/2018/08/19/9503266.htmlhtml

 

 

CLR線程池並不會在CLR初始化時當即創建線程,而是在應用程序要建立線程來運行任務時,線程池才初始化一個線程。
線程池初始化時是沒有線程的,線程池裏的線程的初始化與其餘線程同樣,可是在完成任務之後,該線程不會自行銷燬,而是以掛起的狀態返回到線程池。直到應用程序再次向線程池發出請求時,線程池裏掛起的線程就會再度激活執行任務。
這樣既節省了創建線程所形成的性能損耗,也可讓多個任務反覆重用同一線程,從而在應用程序生存期內節約大量開銷。網絡

經過CLR線程池所創建的線程老是默認爲後臺線程,優先級數爲ThreadPriority.Normal。ide

CLR線程池分爲工做者線程(workerThreads)I/O線程(completionPortThreads)兩種:函數

  • 工做者線程是主要用做管理CLR內部對象的運做,一般用於計算密集的任務。
  • I/O(Input/Output)線程主要用於與外部系統交互信息,如輸入輸出,CPU僅需在任務開始的時候,將任務的參數傳遞給設備,而後啓動硬件設備便可。等任務完成的時候,CPU收到一個通知,通常來講是一個硬件的中斷信號,此時CPU繼續後繼的處理工做。在處理過程當中,CPU是沒必要徹底參與處理過程的,若是正在運行的線程不交出CPU的控制權,那麼線程也只能處於等待狀態,即便操做系統將當前的CPU調度給其餘線程,此時線程所佔用的空間仍是被佔用,而並無CPU處理這個線程,可能出現線程資源浪費的問題。若是這是一個網絡服務程序,每個網絡鏈接都使用一個線程管理,可能出現大量線程都在等待網絡通訊,隨着網絡鏈接的不斷增長,處於等待狀態的線程將會很消耗盡全部的內存資源。能夠考慮使用線程池解決這個問題。

  線程池的最大值通常默認爲1000、2000。當大於此數目的請求時,將保持排隊狀態,直到線程池裏有線程可用。性能

  使用CLR線程池的工做者線程通常有兩種方式:測試

  • 經過ThreadPool.QueueUserWorkItem()方法;
  • 經過委託;

  要注意,不管是經過ThreadPool.QueueUserWorkItem()仍是委託,調用的都是線程池裏的線程。優化

經過如下兩個方法能夠讀取和設置CLR線程池中工做者線程與I/O線程的最大線程數。spa

  1. ThreadPool.GetMax(out in workerThreads,out int completionPortThreads);
  2. ThreadPool.SetMax(int workerThreads,int completionPortThreads);

  若想測試線程池中有多少線程正在投入使用,能夠經過ThreadPool.GetAvailableThreads(out in workThreads,out int conoletionPortThreads)方法。操作系統

方法 說明
GetAvailableThreads 剩餘空閒線程數
GetMaxThreads 最多可用線程數,全部大於此數目的請求將保持排隊狀態,直到線程池線程變爲可用
GetMinThreads 檢索線程池在新請求預測中維護的空閒線程數
QueueUserWorkItem 啓動線程池裏得一個線程(隊列的方式,如線程池暫時沒空閒線程,則進入隊列排隊)
SetMaxThreads 設置線程池中的最大線程數
SetMinThreads 設置線程池最少須要保留的線程數

咱們可使用線程池來解決上面的大部分問題,跟使用單個線程相比,使用線程池有以下優勢:線程

一、縮短應用程序的響應時間。由於在線程池中有線程的線程處於等待分配任務狀態(只要沒有超過線程池的最大上限),無需建立線程。

二、沒必要管理和維護生存週期短暫的線程,不用在建立時爲其分配資源,在其執行完任務以後釋放資源。

三、線程池會根據當前系統特色對池內的線程進行優化處理。

總之使用線程池的做用就是減小建立和銷燬線程的系統開銷。在.NET中有一個線程的類ThreadPool,它提供了線程池的管理。

ThreadPool是一個靜態類,它沒有構造函數,對外提供的函數也所有是靜態的。其中有一個QueueUserWorkItem方法,它有兩種重載形式,以下:

public static bool QueueUserWorkItem(WaitCallback callBack):將方法排入隊列以便執行。此方法在有線程池線程變得可用時執行。

public static bool QueueUserWorkItem(WaitCallback callBack,Object state):將方法排入隊列以便執行,並指定包含該方法所用數據的對象。此方法在有線程池線程變得可用時執行。

QueueUserWorkItem方法中使用的的WaitCallback參數表示一個delegate,它的聲明以下:

public delegate void WaitCallback(Object state)

若是須要傳遞任務信息能夠利用WaitCallback中的state參數,相似於ParameterizedThreadStart委託。

下面是一個ThreadPool的例子,代碼以下:

複製代碼
using System;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading;

namespace ConsoleApp1
{
    class ThreadPoolDemo
    {
        public ThreadPoolDemo()
        {
        }

        public void Work()
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(CountProcess));
            ThreadPool.QueueUserWorkItem(new WaitCallback(GetEnvironmentVariables));
        }
        /// <summary>  
        /// 統計當前正在運行的系統進程信息  
        /// </summary>  
        /// <param name="state"></param>  
        private void CountProcess(object state)
        {
            Process[] processes = Process.GetProcesses();
            foreach (Process p in processes)
            {
                try
                {
                    Console.WriteLine("進程信息:Id:{0},ProcessName:{1},StartTime:{2}", p.Id, p.ProcessName, p.StartTime);
                }
                catch (Win32Exception e)
                {
                    Console.WriteLine("ProcessName:{0}", p.ProcessName);
                }
                finally
                {
                }
            }
            Console.WriteLine("獲取進程信息完畢。");
        }
        /// <summary>  
        /// 獲取當前機器系統變量設置  
        /// </summary>  
        /// <param name="state"></param>  
        public void GetEnvironmentVariables(object state)
        {
            IDictionary list = System.Environment.GetEnvironmentVariables();
            foreach (DictionaryEntry item in list)
            {
                Console.WriteLine("系統變量信息:key={0},value={1}", item.Key, item.Value);
            }
            Console.WriteLine("獲取系統變量信息完畢。");
        }
    }
}
複製代碼
複製代碼
using System;
using System.Threading;

namespace ConsoleApp1
{

    class Program
    {
        static void Main(string[] args)
        {
            ThreadPoolDemo tpd1 = new ThreadPoolDemo();
            tpd1.Work();
            Thread.Sleep(5000);
            Console.WriteLine("OK");
            Console.ReadLine();
        }
    }
}
複製代碼
相關文章
相關標籤/搜索