1. 線程池介紹
??之前我們實現(xiàn)了線程、互斥量、條件變量以及日志的封裝,現(xiàn)在我們可以基于以上內(nèi)容來封裝一個線程池。
??線程池是一種線程使用模式。線程過多會帶來調(diào)度開銷,進而影響緩存局部性和整體性能。而線程池維護著多個線程,等待著監(jiān)督管理者分配可并發(fā)執(zhí)行的任務(wù)。這避免了在處理短時間任務(wù)時創(chuàng)建與銷毀線程的代價。線程池不僅能夠保證內(nèi)核的充分利用,還能防止過分調(diào)度。可用線程數(shù)量應(yīng)該取決于可用的并發(fā)處理器、處理器內(nèi)核、內(nèi)存、網(wǎng)絡(luò)sockets等的數(shù)量。
??線程池的應(yīng)用場景:
需要大量的線程來完成任務(wù),且完成任務(wù)的時間比較短。 比如WEB服務(wù)器完成網(wǎng)頁請求這樣的任務(wù),使用線程池技術(shù)是非常合適的。因為單個任務(wù)小,而任務(wù)數(shù)量巨大,你可以想象?個熱門網(wǎng)站的點擊次數(shù)。 但對于長時間的任務(wù),比如?個Telnet連接請求,線程池的優(yōu)點就不明顯了。因為Telnet會話時間比線程的創(chuàng)建時間大多了。 對性能要求苛刻的應(yīng)用,比如要求服務(wù)器迅速響應(yīng)客戶請求。 接受突發(fā)性的大量請求,但不至于使服務(wù)器因此產(chǎn)生大量線程的應(yīng)用。突發(fā)性大量客戶請求,在沒有線程池情況下,將產(chǎn)生大量線程,雖然理論上大部分操作系統(tǒng)線程數(shù)目最大值不是問題,短時間內(nèi)產(chǎn)生大量線程可能使內(nèi)存到達極限,出現(xiàn)錯誤。
??線程池的種類:
創(chuàng)建固定數(shù)量線程池,循環(huán)從任務(wù)隊列中獲取任務(wù)對象,獲取到任務(wù)對象后,執(zhí)行任務(wù)對象中的任務(wù)接口;浮動線程池,其他同上。
此處,我們選擇固定線程個數(shù)的線程池。

2. 線程池封裝首先我們需要包含需要的頭文件以及命名空間,線程池類中成員變量需要一把鎖、條件變量、條件變量下等待的線程個數(shù)、存放線程的數(shù)組、線程總個數(shù)、存放任務(wù)的任務(wù)隊列以及線程池是否在運行的狀態(tài)表示:代碼語言:JavaScript代碼運行次數(shù):0運行復(fù)制
#include <iostream>#include <string>#include <queue>#include <vector>#include <memory>#include "Log.hpp"#include "Mutex.hpp"#include "Cond.hpp"#include "Thread.hpp"namespace ThreadPoolModule{ using namespace LogModule; using namespace MutexModule; using namespace CondModule; using namespace ThreadModule; using thread_t = std::shared_ptr<Thread>; const static int gthreadnum = 10; template <typename T> class ThreadPool { private: int _threadnum; // 線程個數(shù) Mutex _mutex; Cond _cond; int _waitnum; std::vector<thread_t> _threads; // 存放線程 std::queue<T> _tasks; // 任務(wù)隊列 bool _isrunning; };}
在線程池類的構(gòu)造函數(shù)中我們就可以創(chuàng)建固定數(shù)量的線程并給每個線程綁定執(zhí)行的方法:代碼語言:javascript代碼運行次數(shù):0運行復(fù)制
template <typename T> class ThreadPool { private: bool IsEmpty() { return _tasks.empty(); } void HandlerTask(std::string name) { LOG(LogLevel::INFO) << name << " HandlerTask..."; T task; while (true) { { LockGuard lockguard(_mutex); while (IsEmpty() && _isrunning) { ++_waitnum; _cond.Wait(_mutex); --_waitnum; } if(!_isrunning&&IsEmpty())//為了在退出之前處理完所有的任務(wù) break; task = _tasks.front(); _tasks.pop(); } //處理任務(wù)不需要加鎖保護 task(name); LOG(LogLevel::INFO) << name << " handled a task successfully..."; } LOG(LogLevel::INFO) << name << " exit success..."; } public: // 是要有的,必須是私有的 ThreadPool(int threadnum = gthreadnum) : _threadnum(threadnum), _waitnum(0), _isrunning(false) { // 創(chuàng)建線程 for (int i = 0; i < _threadnum; i++) { _threads.emplace_back(std::make_shared<Thread>(std::bind(&ThreadPool::HandlerTask, this, std::placeholders::_1))); // HandlerTask是成員函數(shù)有this參數(shù),所以不能直接傳參需要綁定 LOG(LogLevel::INFO) << _threads.back()->Name() << "Create Success..."; } LOG(LogLevel::INFO) << "ThreadPool Construct..."; } ~ThreadPool() { } private: int _threadnum; // 線程個數(shù) Mutex _mutex; Cond _cond; int _waitnum; std::vector<thread_t> _threads; // 存放線程 std::queue<T> _tasks; // 任務(wù)隊列 bool _isrunning; };}
如果不清楚線程類中函數(shù)與線程池中的函數(shù)接口之間是怎么相互調(diào)用的可以看看:

線程Start、Stop與Wait:代碼語言:javascript代碼運行次數(shù):0運行復(fù)制
void Start() { if (_isrunning) return; _isrunning = true; for (auto &thread : _threads) { thread->Start(); LOG(LogLevel::INFO) << thread->Name() << " Start Success..."; } } void Stop() { LockGuard lockguard(_mutex); if(_isrunning) { // 3. 不能在入任務(wù)了 _isrunning = false; // 不工作 // 1. 讓線程自己退出(要喚醒) && // 2. 歷史的任務(wù)被處理完了 if(_waitnum>0) _cond.NotifyAll(); } } void Wait() { for (auto &thread : _threads) { thread->Join(); LOG(LogLevel::INFO) << thread->Name() << "Wait Success..."; } }
線程池處理任務(wù)在上述HandlerTask中,我們還需要線程池插入新任務(wù)的方法:代碼語言:javascript代碼運行次數(shù):0運行復(fù)制
bool Enqueue(const T &in) { // 插入任務(wù) LockGuard lockguard(_mutex); if (!_isrunning) return false; _tasks.push(in); if (_waitnum > 0) _cond.Notify(); return true; }
完整實現(xiàn)代碼語言:javascript代碼運行次數(shù):0運行復(fù)制
#pragma once#include#include #include #include #include #include "Log.hpp"#include "Mutex.hpp"#include "Cond.hpp"#include "Thread.hpp"namespace ThreadPoolModule{ using namespace LogModule; using namespace MutexModule; using namespace CondModule; using namespace ThreadModule; using thread_t = std::shared_ptr ; const static int gthreadnum = 10; template class ThreadPool { private: bool IsEmpty() { return _tasks.empty(); } void HandlerTask(std::string name) { LOG(LogLevel::INFO) << name << " HandlerTask..."; T task; while (true) { { LockGuard lockguard(_mutex); while (IsEmpty() && _isrunning) { ++_waitnum; _cond.Wait(_mutex); --_waitnum; } if(!_isrunning&&IsEmpty()) break; task = _tasks.front(); _tasks.pop(); } //處理任務(wù)不需要加鎖保護 task(name); LOG(LogLevel::INFO) << name << " handled a task successfully..."; } LOG(LogLevel::INFO) << name << " exit success..."; } public: // 是要有的,必須是私有的 ThreadPool(int threadnum = gthreadnum) : _threadnum(threadnum), _waitnum(0), _isrunning(false) { // 創(chuàng)建線程 for (int i = 0; i < _threadnum; i++) { _threads.emplace_back(std::make_shared (std::bind(&ThreadPool::HandlerTask, this, std::placeholders::_1))); // HandlerTask是成員函數(shù)有this參數(shù),所以不能直接傳參需要綁定 LOG(LogLevel::INFO) << _threads.back()->Name() << "Create Success..."; } LOG(LogLevel::INFO) << "ThreadPool Construct..."; } void Start() { if (_isrunning) return; _isrunning = true; for (auto &thread : _threads) { thread->Start(); LOG(LogLevel::INFO) << thread->Name() << " Start Success..."; } } void Stop() { LockGuard lockguard(_mutex); if(_isrunning) { // 3. 不能在入任務(wù)了 _isrunning = false; // 不工作 // 1. 讓線程自己退出(要喚醒) && // 2. 歷史的任務(wù)被處理完了 if(_waitnum>0) _cond.NotifyAll(); } } void Wait() { for (auto &thread : _threads) { thread->Join(); LOG(LogLevel::INFO) << thread->Name() << "Wait Success..."; } } bool Enqueue(const T &in) { // 插入任務(wù) LockGuard lockguard(_mutex); if (!_isrunning) return false; _tasks.push(in); if (_waitnum > 0) _cond.Notify(); return true; } ~ThreadPool() { } private: int _threadnum; // 線程個數(shù) Mutex _mutex; Cond _cond; int _waitnum; std::vector _threads; // 存放線程 std::queue _tasks; // 任務(wù)隊列 bool _isrunning; };}
測試函數(shù)如下:
任務(wù)函數(shù):
代碼語言:javascript代碼運行次數(shù):0運行復(fù)制
#pragma once#include <iostream>#include <string>#include <functional>#include "Log.hpp"using namespace LogModule;using task_t = std::function<void(std::string name)>;void Push(std::string name){ LOG(LogLevel::DEBUG) << "我是一個推送數(shù)據(jù)到服務(wù)器的一個任務(wù), 我正在被執(zhí)行" << "[" << name << "]";}
main函數(shù):
代碼語言:javascript代碼運行次數(shù):0運行復(fù)制
#include "ThreadPool.hpp"#include"Task.hpp"using namespace ThreadPoolModule;int main(){ ENABLE_CONSOLE_LOG_STRATEGY(); // ENABLE_FILE_LOG_STRATEGY(); std::unique_ptr<ThreadPool<task_t>> tp = std::make_unique<ThreadPool<task_t>>(); tp->Start(); int cnt = 10; char c; while (cnt) { tp->Enqueue(Push); cnt--; sleep(1); } tp->Stop(); sleep(3); tp->Wait(); return 0;}
結(jié)果如下:代碼語言:javascript代碼運行次數(shù):0運行復(fù)制
./thread_pool [2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [68] - Thread-1Create Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [68] - Thread-2Create Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [68] - Thread-3Create Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [68] - Thread-4Create Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [68] - Thread-5Create Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [68] - Thread-6Create Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [68] - Thread-7Create Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [68] - Thread-8Create Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [68] - Thread-9Create Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [68] - Thread-10Create Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [70] - ThreadPool Construct...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [81] - Thread-1 Start Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [81] - Thread-2 Start Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [81] - Thread-3 Start Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [81] - Thread-4 Start Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [81] - Thread-5 Start Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [81] - Thread-6 Start Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [81] - Thread-7 Start Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [81] - Thread-8 Start Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [81] - Thread-9 Start Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [81] - Thread-10 Start Success...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [30] - Thread-7 HandlerTask...[2025-02-04 09:54:51 ][DEBUG] [2360325] [Task.hpp] [14] - 我是一個推送數(shù)據(jù)到服務(wù)器的一個任務(wù), 我正在被執(zhí)行[Thread-7][2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [51] - Thread-7 handled a task successfully...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [30] - Thread-8 HandlerTask...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [30] - Thread-9 HandlerTask...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [30] - Thread-6 HandlerTask...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [30] - Thread-10 HandlerTask...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [30] - Thread-5 HandlerTask...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [30] - Thread-4 HandlerTask...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [30] - Thread-3 HandlerTask...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [30] - Thread-2 HandlerTask...[2025-02-04 09:54:51 ][INFO] [2360325] [ThreadPool.hpp] [30] - Thread-1 HandlerTask...[2025-02-04 09:54:52 ][DEBUG] [2360325] [Task.hpp] [14] - 我是一個推送數(shù)據(jù)到服務(wù)器的一個任務(wù), 我正在被執(zhí)行[Thread-7][2025-02-04 09:54:52 ][INFO] [2360325] [ThreadPool.hpp] [51] - Thread-7 handled a task successfully...[2025-02-04 09:54:53 ][DEBUG] [2360325] [Task.hpp] [14] - 我是一個推送數(shù)據(jù)到服務(wù)器的一個任務(wù), 我正在被執(zhí)行[Thread-8][2025-02-04 09:54:53 ][INFO] [2360325] [ThreadPool.hpp] [51] - Thread-8 handled a task successfully...[2025-02-04 09:54:54 ][DEBUG] [2360325] [Task.hpp] [14] - 我是一個推送數(shù)據(jù)到服務(wù)器的一個任務(wù), 我正在被執(zhí)行[Thread-9][2025-02-04 09:54:54 ][INFO] [2360325] [ThreadPool.hpp] [51] - Thread-9 handled a task successfully...[2025-02-04 09:54:55 ][DEBUG] [2360325] [Task.hpp] [14] - 我是一個推送數(shù)據(jù)到服務(wù)器的一個任務(wù), 我正在被執(zhí)行[Thread-6][2025-02-04 09:54:55 ][INFO] [2360325] [ThreadPool.hpp] [51] - Thread-6 handled a task successfully...[2025-02-04 09:54:56 ][DEBUG] [2360325] [Task.hpp] [14] - 我是一個推送數(shù)據(jù)到服務(wù)器的一個任務(wù), 我正在被執(zhí)行[Thread-10][2025-02-04 09:54:56 ][INFO] [2360325] [ThreadPool.hpp] [51] - Thread-10 handled a task successfully...[2025-02-04 09:54:57 ][DEBUG] [2360325] [Task.hpp] [14] - 我是一個推送數(shù)據(jù)到服務(wù)器的一個任務(wù), 我正在被執(zhí)行[Thread-5][2025-02-04 09:54:57 ][INFO] [2360325] [ThreadPool.hpp] [51] - Thread-5 handled a task successfully...[2025-02-04 09:54:58 ][DEBUG] [2360325] [Task.hpp] [14] - 我是一個推送數(shù)據(jù)到服務(wù)器的一個任務(wù), 我正在被執(zhí)行[Thread-4][2025-02-04 09:54:58 ][INFO] [2360325] [ThreadPool.hpp] [51] - Thread-4 handled a task successfully...[2025-02-04 09:54:59 ][DEBUG] [2360325] [Task.hpp] [14] - 我是一個推送數(shù)據(jù)到服務(wù)器的一個任務(wù), 我正在被執(zhí)行[Thread-3][2025-02-04 09:54:59 ][INFO] [2360325] [ThreadPool.hpp] [51] - Thread-3 handled a task successfully...[2025-02-04 09:55:00 ][DEBUG] [2360325] [Task.hpp] [14] - 我是一個推送數(shù)據(jù)到服務(wù)器的一個任務(wù), 我正在被執(zhí)行[Thread-2][2025-02-04 09:55:00 ][INFO] [2360325] [ThreadPool.hpp] [51] - Thread-2 handled a task successfully...[2025-02-04 09:55:01 ][INFO] [2360325] [ThreadPool.hpp] [54] - Thread-7 exit success...[2025-02-04 09:55:01 ][INFO] [2360325] [ThreadPool.hpp] [54] - Thread-8 exit success...[2025-02-04 09:55:01 ][INFO] [2360325] [ThreadPool.hpp] [54] - Thread-9 exit success...[2025-02-04 09:55:01 ][INFO] [2360325] [ThreadPool.hpp] [54] - Thread-6 exit success...[2025-02-04 09:55:01 ][INFO] [2360325] [ThreadPool.hpp] [54] - Thread-10 exit success...[2025-02-04 09:55:01 ][INFO] [2360325] [ThreadPool.hpp] [54] - Thread-5 exit success...[2025-02-04 09:55:01 ][INFO] [2360325] [ThreadPool.hpp] [54] - Thread-4 exit success...[2025-02-04 09:55:01 ][INFO] [2360325] [ThreadPool.hpp] [54] - Thread-3 exit success...[2025-02-04 09:55:01 ][INFO] [2360325] [ThreadPool.hpp] [54] - Thread-2 exit success...[2025-02-04 09:55:01 ][INFO] [2360325] [ThreadPool.hpp] [54] - Thread-1 exit success...[2025-02-04 09:55:04 ][INFO] [2360325] [ThreadPool.hpp] [101] - Thread-1Wait Success...[2025-02-04 09:55:04 ][INFO] [2360325] [ThreadPool.hpp] [101] - Thread-2Wait Success...[2025-02-04 09:55:04 ][INFO] [2360325] [ThreadPool.hpp] [101] - Thread-3Wait Success...[2025-02-04 09:55:04 ][INFO] [2360325] [ThreadPool.hpp] [101] - Thread-4Wait Success...[2025-02-04 09:55:04 ][INFO] [2360325] [ThreadPool.hpp] [101] - Thread-5Wait Success...[2025-02-04 09:55:04 ][INFO] [2360325] [ThreadPool.hpp] [101] - Thread-6Wait Success...[2025-02-04 09:55:04 ][INFO] [2360325] [ThreadPool.hpp] [101] - Thread-7Wait Success...[2025-02-04 09:55:04 ][INFO] [2360325] [ThreadPool.hpp] [101] - Thread-8Wait Success...[2025-02-04 09:55:04 ][INFO] [2360325] [ThreadPool.hpp] [101] - Thread-9Wait Success...[2025-02-04 09:55:04 ][INFO] [2360325] [ThreadPool.hpp] [101] - Thread-10Wait Success...
3. 線程安全的單例模式單例模式的特點
??某些類, 只應(yīng)該具有?個對象(實例), 就稱之為單例。
??在很多服務(wù)器開發(fā)場景中, 經(jīng)常需要讓服務(wù)器加載很多的數(shù)據(jù) (上百G) 到內(nèi)存中. 此時往往要用一個單例的類來管理這些數(shù)據(jù)。
餓漢實現(xiàn)方式和懶漢實現(xiàn)方式
[洗碗的例子]
吃完飯, 立刻洗碗, 這種就是餓漢方式. 因為下一頓吃的時候可以立刻拿著碗就能吃飯.吃完飯, 先把碗放下, 然后下?頓飯用到這個碗了再洗碗, 就是懶漢方式.餓漢方式實現(xiàn)單例模式:代碼語言:javascript代碼運行次數(shù):0運行復(fù)制
template <typename T>class Singleton {static T data;public:static T* GetInstance() {return &data;}};
懶漢方式實現(xiàn)單例模式:代碼語言:javascript代碼運行次數(shù):0運行復(fù)制
template <typename T>class Singleton { static T* inst;public: static T* GetInstance() { if (inst == NULL) { inst = new T(); } return inst; }};
懶漢方式實現(xiàn)單例模式(線程安全版本):代碼語言:javascript代碼運行次數(shù):0運行復(fù)制
// 懶漢模式, 線程安全template <typename T>class Singleton {volatile static T* inst; // 需要設(shè)置 volatile 關(guān)鍵字, 否則可能被編譯器優(yōu)化.static std::mutex lock;public:static T* GetInstance() {if (inst == NULL) // 雙重判定空指針, 降低鎖沖突的概率, 提?性能.{ lock.lock(); // 使?互斥鎖, 保證多線程情況下也只調(diào)??次 new.if (inst == NULL) {inst = new T();}lock.unlock(); }return inst;}};
注意事項:
加鎖解鎖的位置雙重 if 判定, 避免不必要的鎖競爭volatile關(guān)鍵字防止過度優(yōu)化4. 單例式線程池
??我們使用的是餓漢實現(xiàn)方式來實現(xiàn)單例線程池,首先我們需要創(chuàng)建靜態(tài)全局的線程池指針以及鎖:
代碼語言:javascript代碼運行次數(shù):0運行復(fù)制
#include <iostream>#include <string>#include <queue>#include <vector>#include <memory>#include "Log.hpp"#include "Mutex.hpp"#include "Cond.hpp"#include "Thread.hpp"namespace ThreadPoolModule{ using namespace LogModule; using namespace MutexModule; using namespace CondModule; using namespace ThreadModule; using thread_t = std::shared_ptr<Thread>; const static int gthreadnum = 10; template <typename T> class ThreadPool { private: int _threadnum; // 線程個數(shù) Mutex _mutex; Cond _cond; int _waitnum; std::vector<thread_t> _threads; // 存放線程 std::queue<T> _tasks; // 任務(wù)隊列 bool _isrunning;// 添加單例模式static ThreadPool<T> *_instance;static Mutex _lock;};//在類外初始化template <typename T>ThreadPool<T> *ThreadPool<T>::_instance = nullptr;template <typename T>Mutex ThreadPool<T>::_lock;}
然后獲取線程池單例函數(shù):代碼語言:javascript代碼運行次數(shù):0運行復(fù)制
static ThreadPool<T> *GetInstance() { if (_instance == nullptr) { LockGuard lockguard(_lock); if (_instance == nullptr) { _instance = new ThreadPool<T>(); _instance->Start(); } } LOG(LogLevel::DEBUG) << "GetInstance success..."; return _instance; }
最后將構(gòu)造函數(shù)以及Start函數(shù)設(shè)為私有以及將賦值和拷貝構(gòu)造禁用。完整實現(xiàn)代碼語言:javascript代碼運行次數(shù):0運行復(fù)制
#pragma once#include#include #include #include #include #include "Log.hpp"#include "Mutex.hpp"#include "Cond.hpp"#include "Thread.hpp"namespace ThreadPoolModule{ using namespace LogModule; using namespace MutexModule; using namespace CondModule; using namespace ThreadModule; using thread_t = std::shared_ptr ; const static int gthreadnum = 10; template class ThreadPool { private: // 是要有的,必須是私有的 ThreadPool(int threadnum = gthreadnum) : _threadnum(threadnum), _waitnum(0), _isrunning(false) { // 創(chuàng)建線程 for (int i = 0; i < _threadnum; i++) { _threads.emplace_back(std::make_shared (std::bind(&ThreadPool::HandlerTask, this, std::placeholders::_1))); // HandlerTask是成員函數(shù)有this參數(shù),所以不能直接傳參需要綁定 LOG(LogLevel::INFO) << _threads.back()->Name() << "Create Success..."; } LOG(LogLevel::INFO) << "ThreadPool Construct..."; } bool IsEmpty() { return _tasks.empty(); } void HandlerTask(std::string name) { LOG(LogLevel::INFO) << name << " HandlerTask..."; T task; while (true) { { LockGuard lockguard(_mutex); while (IsEmpty() && _isrunning) { ++_waitnum; _cond.Wait(_mutex); --_waitnum; } if (!_isrunning && IsEmpty()) break; task = _tasks.front(); _tasks.pop(); } // 處理任務(wù)不需要加鎖保護 task(name); LOG(LogLevel::INFO) << name << " handled a task successfully..."; } LOG(LogLevel::INFO) << name << " exit success..."; } void Start() { if (_isrunning) return; _isrunning = true; for (auto &thread : _threads) { thread->Start(); LOG(LogLevel::INFO) << thread->Name() << " Start Success..."; } } // 賦值、拷?禁? ThreadPool &operator=(const ThreadPool &) = delete; ThreadPool(const ThreadPool &) = delete; public: static ThreadPool<T> *GetInstance() { if (_instance == nullptr) { LockGuard lockguard(_lock); if (_instance == nullptr) { _instance = new ThreadPool<T>(); _instance->Start(); } } LOG(LogLevel::DEBUG) << "GetInstance success..."; return _instance; } void Stop() { LockGuard lockguard(_mutex); if (_isrunning) { // 3. 不能在入任務(wù)了 _isrunning = false; // 不工作 // 1. 讓線程自己退出(要喚醒) && // 2. 歷史的任務(wù)被處理完了 if (_waitnum > 0) _cond.NotifyAll(); } } void Wait() { for (auto &thread : _threads) { thread->Join(); LOG(LogLevel::INFO) << thread->Name() << "Wait Success..."; } } bool Enqueue(const T &in) { // 插入任務(wù) LockGuard lockguard(_mutex); if (!_isrunning) return false; _tasks.push(in); if (_waitnum > 0) _cond.Notify(); return true; } ~ThreadPool() { } private: int _threadnum; // 線程個數(shù) Mutex _mutex; Cond _cond; int _waitnum; std::vector _threads; // 存放線程 std::queue _tasks; // 任務(wù)隊列 bool _isrunning; // 單例模式 static ThreadPool *_instance; static Mutex _lock; }; // 在類外初始化 template ThreadPool *ThreadPool ::_instance = nullptr; template Mutex ThreadPool ::_lock;}
測試函數(shù):代碼語言:javascript代碼運行次數(shù):0運行復(fù)制
#include <iostream>#include <functional>#include <unistd.h>#include "ThreadPool.hpp"using namespace ThreadPoolModule;using task_t = std::function<void(std::string name)>;void DownLoad(std::string name){ std::cout << "this is a task" << std::endl;}int main(){ ENABLE_CONSOLE_LOG_STRATEGY(); int cnt = 10; while (cnt) { ThreadPool<task_t>::GetInstance()->Enqueue(DownLoad); sleep(1); cnt--; } ThreadPool<task_t>::GetInstance()->Stop(); sleep(5); ThreadPool<task_t>::GetInstance()->Wait(); return 0;}
結(jié)果如下:代碼語言:javascript代碼運行次數(shù):0運行復(fù)制
tutu@hecs-16648:~/linux/ThreadPool$ ./thread_pool [2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [36] - Thread-1Create Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [36] - Thread-2Create Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [36] - Thread-3Create Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [36] - Thread-4Create Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [36] - Thread-5Create Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [36] - Thread-6Create Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [36] - Thread-7Create Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [36] - Thread-8Create Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [36] - Thread-9Create Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [36] - Thread-10Create Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [38] - ThreadPool Construct...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [76] - Thread-1 Start Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [76] - Thread-2 Start Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [76] - Thread-3 Start Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [76] - Thread-4 Start Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [76] - Thread-5 Start Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [76] - Thread-6 Start Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [76] - Thread-7 Start Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [76] - Thread-8 Start Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [76] - Thread-9 Start Success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [76] - Thread-10 Start Success...[2025-02-04 14:40:58 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [43] - Thread-7 HandlerTask...this is a task[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [43] - Thread-8 HandlerTask...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [64] - Thread-7 handled a task successfully...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [43] - Thread-6 HandlerTask...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [43] - Thread-9 HandlerTask...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [43] - Thread-10 HandlerTask...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [43] - Thread-5 HandlerTask...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [43] - Thread-4 HandlerTask...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [43] - Thread-3 HandlerTask...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [43] - Thread-2 HandlerTask...[2025-02-04 14:40:58 ][INFO] [2368011] [ThreadPool.hpp] [43] - Thread-1 HandlerTask...[2025-02-04 14:40:59 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...this is a task[2025-02-04 14:40:59 ][INFO] [2368011] [ThreadPool.hpp] [64] - Thread-8 handled a task successfully...[2025-02-04 14:41:00 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...this is a task[2025-02-04 14:41:00 ][INFO] [2368011] [ThreadPool.hpp] [64] - Thread-7 handled a task successfully...[2025-02-04 14:41:01 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...this is a task[2025-02-04 14:41:01 ][INFO] [2368011] [ThreadPool.hpp] [64] - Thread-6 handled a task successfully...[2025-02-04 14:41:02 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...this is a task[2025-02-04 14:41:02 ][INFO] [2368011] [ThreadPool.hpp] [64] - Thread-9 handled a task successfully...[2025-02-04 14:41:03 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...this is a task[2025-02-04 14:41:03 ][INFO] [2368011] [ThreadPool.hpp] [64] - Thread-10 handled a task successfully...[2025-02-04 14:41:04 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...this is a task[2025-02-04 14:41:04 ][INFO] [2368011] [ThreadPool.hpp] [64] - Thread-5 handled a task successfully...[2025-02-04 14:41:05 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...this is a task[2025-02-04 14:41:05 ][INFO] [2368011] [ThreadPool.hpp] [64] - Thread-4 handled a task successfully...[2025-02-04 14:41:06 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...this is a task[2025-02-04 14:41:06 ][INFO] [2368011] [ThreadPool.hpp] [64] - Thread-3 handled a task successfully...[2025-02-04 14:41:07 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...this is a task[2025-02-04 14:41:07 ][INFO] [2368011] [ThreadPool.hpp] [64] - Thread-2 handled a task successfully...[2025-02-04 14:41:08 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...[2025-02-04 14:41:08 ][INFO] [2368011] [ThreadPool.hpp] [66] - Thread-8 exit success...[2025-02-04 14:41:08 ][INFO] [2368011] [ThreadPool.hpp] [66] - Thread-7 exit success...[2025-02-04 14:41:08 ][INFO] [2368011] [ThreadPool.hpp] [66] - Thread-6 exit success...[2025-02-04 14:41:08 ][INFO] [2368011] [ThreadPool.hpp] [66] - Thread-9 exit success...[2025-02-04 14:41:08 ][INFO] [2368011] [ThreadPool.hpp] [66] - Thread-10 exit success...[2025-02-04 14:41:08 ][INFO] [2368011] [ThreadPool.hpp] [66] - Thread-5 exit success...[2025-02-04 14:41:08 ][INFO] [2368011] [ThreadPool.hpp] [66] - Thread-4 exit success...[2025-02-04 14:41:08 ][INFO] [2368011] [ThreadPool.hpp] [66] - Thread-3 exit success...[2025-02-04 14:41:08 ][INFO] [2368011] [ThreadPool.hpp] [66] - Thread-2 exit success...[2025-02-04 14:41:08 ][INFO] [2368011] [ThreadPool.hpp] [66] - Thread-1 exit success...[2025-02-04 14:41:13 ][DEBUG] [2368011] [ThreadPool.hpp] [95] - GetInstance success...[2025-02-04 14:41:13 ][INFO] [2368011] [ThreadPool.hpp] [116] - Thread-1Wait Success...[2025-02-04 14:41:13 ][INFO] [2368011] [ThreadPool.hpp] [116] - Thread-2Wait Success...[2025-02-04 14:41:13 ][INFO] [2368011] [ThreadPool.hpp] [116] - Thread-3Wait Success...[2025-02-04 14:41:13 ][INFO] [2368011] [ThreadPool.hpp] [116] - Thread-4Wait Success...[2025-02-04 14:41:13 ][INFO] [2368011] [ThreadPool.hpp] [116] - Thread-5Wait Success...[2025-02-04 14:41:13 ][INFO] [2368011] [ThreadPool.hpp] [116] - Thread-6Wait Success...[2025-02-04 14:41:13 ][INFO] [2368011] [ThreadPool.hpp] [116] - Thread-7Wait Success...[2025-02-04 14:41:13 ][INFO] [2368011] [ThreadPool.hpp] [116] - Thread-8Wait Success...[2025-02-04 14:41:13 ][INFO] [2368011] [ThreadPool.hpp] [116] - Thread-9Wait Success...[2025-02-04 14:41:13 ][INFO] [2368011] [ThreadPool.hpp] [116] - Thread-10Wait Success...