首頁 後端開發 C#.Net教程 c#自己實作執行緒池功能(一)

c#自己實作執行緒池功能(一)

Dec 27, 2016 pm 02:36 PM

線程池的技術背景

在物件導向程式設計中,創建和銷毀物件是很費時間的,因為創建一個物件要獲取記憶體資源或者其它更多資源,所以提高服務程式效率的一個手段就是盡可能減少創建和銷毀物件的次數,特別是一些很耗資源的物件創建和銷毀。如何利用已有物件來服務就是一個需要解決的關鍵問題,其實這就是一些"池化資源"技術產生的原因。例如大家所熟悉的資料庫連結池正是遵循這個想法而產生的,本文將介紹的線程池技術同樣符合這個想法。

線程池技術如何提高伺服器程式的效能

我所提到伺服器程式是指能夠接受客戶請求並能處理請求的程序,而不只是指那些接受網路客戶請求的網路伺服器程式。

多執行緒技術主要解決處理器單元內多個執行緒執行的問題,它可以顯著減少處理器單元的閒置時間,增加處理器單元的吞吐能力。但如果對多執行緒應用不當,會增加單一任務的處理時間。可以舉一個簡單的例子:

假設在一台伺服器完成一項任務的時間為T

T1 创建线程的时间
 T2 在线程中执行任务的时间,包括线程间同步所需时间
 T3 线程销毁的时间
登入後複製

顯然T = T1+T2+T3。注意這是一個極度簡化的假設。

可以看出T1,T3是多執行緒本身的帶來的開銷,我們渴望減少T1,T3所花費的時間,從而減少T的時間。但一些線程的使用者並沒有註意到這一點,所以在程式中頻繁的創建或銷毀線程,這導致T1和T3在T中佔有相當比例。顯然這是突顯了線程的弱點(T1,T3),而不是優點(並發性)。

線程池技術正是關注如何縮短或調整T1,T3時間的技術,從而提高伺服器程式效能的。它把T1,T3分別安排在伺服器程式的啟動和結束的時間段或一些空閒的時間段,這樣在伺服器程式處理客戶請求時,不會有T1,T3的開銷了。

執行緒池不僅調整T1,T3產生的時間段,而且它還顯著減少了創建執行緒的數目。在看一個例子:

假設一個伺服器一天要處理50000個請求,並且每個請求需要一個單獨的執行緒完成。我們比較利用線程池技術和不利於線程池技術的伺服器處理這些請求時所產生的總線程數。在線程池中,線程數一般是固定的,所以產生線程總數不會超過線程池中線程的數目或者上限(以下簡稱線程池尺寸),而如果伺服器不利用線程池來處理這些請求則線程總數為50000。一般線程池尺寸是遠小於50000。所以利用線程池的伺服器程式不會為了創建50000而在處理請求時浪費時間,從而提高效率。

這些都是假設,不能充分說明問題,下面我將討論線程池的簡單實現並對該程序進行對比測試,以說明線程技術優點及應用領域。

執行緒池的簡單實作及對比測試

一般一個簡單執行緒池至少包含下列組成部分。

執行緒池管理器(ThreadPoolManager):用於建立並管理執行緒池

工作執行緒(WorkThread): 執行緒池中執行緒

任務介面(Task):每個任務必須實現的接口,以供工作執行緒調度任務的執行。

任務佇列:用於存放沒有處理的任務。提供一種緩衝機制。 
接下來我示範了一個 最簡單的執行緒池。沒有進行任何優化的。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Threading;
 
namespace ThreadManager
{
    public class ThreadPoolManager
    {
        private int MaxThreadNum;
        private int MinThreadNum;
        private int GrowStepNum;
        //线程数量
        public int ThreadNum{get;set;}
        //默认线程数量
        public int DefaultThreadNum { get; set; }
 
        private Queue<task> TaskQueue;
        private Queue<workthread> WorkThreadList;
 
        public ThreadPoolManager(int i)
        {
            TaskQueue = new Queue<task>();
            WorkThreadList = new Queue<workthread>();
            DefaultThreadNum = 10;
            if (i > 0)
                DefaultThreadNum = i;
            CreateThreadPool(i);
        }
        public ThreadPoolManager():this(10)
        {
        }
        public bool IsAllTaskFinish()
        {
            return TaskQueue.Count == 0;
        }
        public void CreateThreadPool(int i)
        {
            if (WorkThreadList == null)
                WorkThreadList = new Queue<workthread>();
            lock (WorkThreadList)
            {
                for (int j = 0; j < i;j++)
                {
                    ThreadNum++;
                    WorkThread workthread = new WorkThread(ref TaskQueue,ThreadNum);
                    WorkThreadList.Enqueue(workthread);
                }
            }
        }
        public void AddTask(Task task)
        {
            
            if (task == null)
                return;
            lock (TaskQueue)
            {
                TaskQueue.Enqueue(task);
            }
            //Monitor.Enter(TaskQueue);
            //TaskQueue.Enqueue(task);
            //Monitor.Exit(TaskQueue);
        }
        public void CloseThread()
        {
            //Object obj = null;
            while (WorkThreadList.Count != 0)
            {
                try
                {
                    WorkThread workthread = WorkThreadList.Dequeue();
                    workthread.CloseThread();
                    continue;
                }
                catch (Exception)
                {
                }
                break;
            }
        }
    }
}
</workthread></workthread></task></workthread></task>
登入後複製

工作線程類

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
 
namespace ThreadManager
{
    public class WorkThread
    {
        public int ThreadNum { get; set; }
        private bool flag;
        private Queue<task> TaskQueue;
        private Task task;
        public WorkThread(ref Queue<task> queue, int i)
        {
            this.TaskQueue = queue;
            ThreadNum = i;
            flag = true;
            new Thread(run).Start();
        }
        public void run()
        {
            while (flag && TaskQueue != null)
            {
                //获取任务
                lock (TaskQueue)
                {
                    try
                    {
                            task = TaskQueue.Dequeue();
                    }
                    catch (Exception)
                    {
                        task = null;
                    }
                    if (task == null)
                        continue;
                }
                try
                {
                    task.SetEnd(false);
                    task.StartTask();
                }
                catch (Exception)
                {
                }
                try
                {
                    if (!task.IsEnd())
                    {
                        task.SetEnd(false);
                        task.EndTask();
                    }
                }
                catch (Exception)
                {
                }
 
            }//end of while
        }
        public void CloseThread()
        {
            flag = false;
            try
            {
                if (task != null)
                    task.EndTask();
            }
            catch (Exception)
            {   
            }
        }
    }
}</task></task>
登入後複製

task類和實現類

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace ThreadManager
{
    public interface Task
    {
        /// <summary>
        /// set flag of task.
        /// </summary>
        void SetEnd(bool flag);
        /// <summary>
        /// start task.
        /// </summary>
        void StartTask();
        /// <summary>
        /// end task.
        /// </summary>
        void EndTask();
        /// <summary>
        /// get status of task.
        /// </summary>
        /// <returns></returns>
        bool IsEnd();
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
 
namespace ThreadManager
{
    public class TestTask:Task
    {
        private bool is_end;
        public void SetEnd(bool flag)
        {
            is_end = flag;
        }
        public void StartTask()
        {
            Run();
        }
        public void EndTask()
        {
            is_end = true;
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ":"+"结束!");
        }
        public bool IsEnd()
        {
            return is_end;
        }
        public void Run()
        {
            for (int i = 0; i < 1000; i++)
            {
                Console.WriteLine(Thread.CurrentThread.ManagedThreadId+":"+i);
            }
        }
 
    }
}
登入後複製

這個簡單的模型存在的問題是,很多時候獲取TASK都是在不斷的嘗試,使得性能降的很低,需要改進的方法是增加一個信號量的機制,不讓程式空轉!

在下一篇文章中我會進行最佳化,使得線程池真正的提高效率! 

 以上就是c#自己實作執行緒池功能(一)的內容,更多相關內容請關注PHP中文網(www.php.cn)!


本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

使用 C# 的活動目錄 使用 C# 的活動目錄 Sep 03, 2024 pm 03:33 PM

使用 C# 的 Active Directory 指南。在這裡,我們討論 Active Directory 在 C# 中的介紹和工作原理以及語法和範例。

C# 序列化 C# 序列化 Sep 03, 2024 pm 03:30 PM

C# 序列化指南。這裡我們分別討論C#序列化物件的介紹、步驟、工作原理和範例。

C# 中的隨機數產生器 C# 中的隨機數產生器 Sep 03, 2024 pm 03:34 PM

C# 隨機數產生器指南。在這裡,我們討論隨機數產生器的工作原理、偽隨機數和安全數的概念。

C# 資料網格視圖 C# 資料網格視圖 Sep 03, 2024 pm 03:32 PM

C# 資料網格視圖指南。在這裡,我們討論如何從 SQL 資料庫或 Excel 檔案載入和匯出資料網格視圖的範例。

C# 中的階乘 C# 中的階乘 Sep 03, 2024 pm 03:34 PM

C# 階乘指南。這裡我們討論 C# 中階乘的介紹以及不同的範例和程式碼實作。

C# 中的模式 C# 中的模式 Sep 03, 2024 pm 03:33 PM

C# 模式指南。在這裡,我們討論 C# 中模式的介紹和前 3 種類型,以及其範例和程式碼實作。

c#多線程和異步的區別 c#多線程和異步的區別 Apr 03, 2025 pm 02:57 PM

多線程和異步的區別在於,多線程同時執行多個線程,而異步在不阻塞當前線程的情況下執行操作。多線程用於計算密集型任務,而異步用於用戶交互操作。多線程的優勢是提高計算性能,異步的優勢是不阻塞 UI 線程。選擇多線程還是異步取決於任務性質:計算密集型任務使用多線程,與外部資源交互且需要保持 UI 響應的任務使用異步。

C# 中的質數 C# 中的質數 Sep 03, 2024 pm 03:35 PM

C# 質數指南。這裡我們討論c#中素數的介紹和範例以及程式碼實作。

See all articles