C++ 學(xué)習(xí)筆記實(shí)戰(zhàn)寫(xiě)一個(gè)簡(jiǎn)單的線程池示例
線程池的工作原理
- 在構(gòu)造函數(shù)中,創(chuàng)建指定數(shù)量的工作線程,并將它們存儲(chǔ)在
workers
向量中。 - 每個(gè)工作線程都通過(guò)無(wú)限循環(huán)來(lái)執(zhí)行任務(wù)隊(duì)列中的任務(wù)。
- 設(shè)置一個(gè)
public
函數(shù),接收新任務(wù),封裝為std::function<void()>
并添加到任務(wù)隊(duì)列中。 - 等待的工作線程會(huì)被喚醒并獲取任務(wù)執(zhí)行,直到線程池被銷毀或調(diào)用
stop()
函數(shù)停止。
第一步, 創(chuàng)建指定數(shù)量的工作線程
class ThreadPool { public: ThreadPool(int num){ // 啟動(dòng)指定數(shù)量的線程 for(int i = 0; i < num; i++ ) { // 使用循環(huán)創(chuàng)建指定數(shù)量的工作線程。每個(gè)工作線程都是通過(guò)`emplace_back`函數(shù)向`workers`容器中添加一個(gè)lambda函數(shù)創(chuàng)建的 // 添加一個(gè)lambda函數(shù)即為創(chuàng)建一個(gè)線程 workers.emplace_back([this]{ // code... }); } } private: // 用向量?jī)?chǔ)存線程 std::vector<std::thread> workers; }
第二步在每個(gè)線程中啟動(dòng)死循環(huán),依次從任務(wù)隊(duì)列中取中任務(wù),直到隊(duì)列為空或設(shè)置stop
標(biāo)識(shí)為true;
第二步,在第一步基礎(chǔ)上,添加代碼
class ThreadPool { public: ThreadPool(int num): stoped(false) { // 啟動(dòng)指定數(shù)量的線程 for(int i = 0; i < num; i++ ) { // 使用循環(huán)創(chuàng)建指定數(shù)量的工作線程。每個(gè)工作線程都是通過(guò)`emplace_back`函數(shù)向`workers`容器中添加一個(gè)lambda函數(shù)創(chuàng)建的 // 添加一個(gè)lambda函數(shù)即為創(chuàng)建一個(gè)線程 workers.emplace_back([this]{ // 死循環(huán) while(true) { // 設(shè)置一個(gè)task接收從隊(duì)列中取出的任務(wù) std::function<void()> task; { // 從隊(duì)列中取任務(wù)要加鎖,以避免重復(fù)讀 std::unique_lock<std::mutex> lock(ququeMutex); // 如果stoped==true,或任務(wù)不為空,則使當(dāng)前線程等待 condition.wait(lock, [this]{ return stroped || !tasks.empty(); }); // 設(shè)置stoped為true后,則等到任務(wù)都完成為退出(tasks任務(wù)隊(duì)列為空) if (stoped && tasks.empty()) { return; } // 從隊(duì)列中接收任務(wù) task = std::move(tasks.front()); // 彈出已經(jīng)接收的任務(wù) tasks.pop(); } // 以上代碼使用{}限制了作用域,在域內(nèi)啟用的鎖queueMutex在域結(jié)束后自動(dòng)解鎖 } }); } } // 設(shè)置停止標(biāo)識(shí) void stop() { std::unique_lock<std::mutex> lock(queueMutex); stoped = true; } private: // 用向量?jī)?chǔ)存線程 std::vector<std::thread> workers; // 工作隊(duì)列 std::queue<std::function<void()> tasks; // 隊(duì)列互斥鎖 std::mutex queueMutex; // 條件變量 std::condition_variable condition; // stop標(biāo)識(shí) bool stoped; }
第三步,設(shè)置一個(gè)函數(shù)用從外部接收任務(wù)
// class ThreadBool... template<class F> void enqueue(F&& f){ { // 在域內(nèi)啟用鎖, 保證加任務(wù)時(shí)沒(méi)沖突 std::unique_lock<std::mutex> lock(queueMutex); // 轉(zhuǎn)發(fā)任務(wù)到tasks隊(duì)列中 tasks.emplace(std::forword<F>(f)); } // 通知一個(gè)線程起來(lái)接活 condition.notify_one(); } // ...
第四步,設(shè)置析構(gòu)函數(shù)等待所有線程執(zhí)行完成
// class ThreadBool ~ThreadPool(){ ?。? std::unique_lock<std::mutex> lock(queueMutex); stoded = true; } // 阻塞等待所有線程 for(std::thread& worker: workers){ worker.join(); } }
最后完整代碼
#include <vector> #include <thread> #include <queue> #include <mutex> #include <condition_variable> #include <functional> #include <iostream> thread_local int thr_num; class Task{ public run(int num = 0) { thr_num = num; std::cout << "當(dāng)前任務(wù)號(hào)是" << thr_num << std::endl; } } class ThreadPool { public: ThreadPool(int num): stoped(false) { // 啟動(dòng)指定數(shù)量的線程 for(int i = 0; i < num; i++ ) { // 使用循環(huán)創(chuàng)建指定數(shù)量的工作線程。每個(gè)工作線程都是通過(guò)`emplace_back`函數(shù)向`workers`容器中添加一個(gè)lambda函數(shù)創(chuàng)建的 // 添加一個(gè)lambda函數(shù)即為創(chuàng)建一個(gè)線程 workers.emplace_back([this]{ // 死循環(huán) while(true) { // 設(shè)置一個(gè)task接收從隊(duì)列中取出的任務(wù) std::function<void()> task; { // 從隊(duì)列中取任務(wù)要加鎖,以避免重復(fù)讀 std::unique_lock<std::mutex> lock(ququeMutex); // 如果stoped==true,或任務(wù)不為空,則使當(dāng)前線程等待 condition.wait(lock, [this]{ return stroped || !tasks.empty(); }); // 設(shè)置stoped為true后,則等到任務(wù)都完成為退出(tasks任務(wù)隊(duì)列為空) if (stoped && tasks.empty()) { return; } // 從隊(duì)列中接收任務(wù) task = std::move(tasks.front()); // 彈出已經(jīng)接收的任務(wù) tasks.pop(); } // 以上代碼使用{}限制了作用域,在域內(nèi)啟用的鎖queueMutex在域結(jié)束后自動(dòng)解鎖 } }); } } // 設(shè)置停止標(biāo)識(shí) void stop() { std::unique_lock(std::mutex ) stoped = true; } private: // 用向量?jī)?chǔ)存線程 std::vector<std::thread> workers; // 工作隊(duì)列 std::queue<std::function<void()> tasks; // 隊(duì)列互斥鎖 std::mutex queueMutex; // 條件變量 std::condition_variable condition; // stop標(biāo)識(shí) bool stoped; } int main() { ThreadPool tp(4); Task task; for(int i = 0; i<4; i++) { int num = i; tp.enqueue([num, &task] { task.run(num); }); } return 0; }
以上就是C++ 學(xué)習(xí)筆記實(shí)戰(zhàn)寫(xiě)一個(gè)簡(jiǎn)單的線程池示例的詳細(xì)內(nèi)容,更多關(guān)于C++ 線程池的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- 基于C++17實(shí)現(xiàn)的手寫(xiě)線程池
- 基于C++11實(shí)現(xiàn)手寫(xiě)線程池的示例代碼
- C++單例模式實(shí)現(xiàn)線程池的示例代碼
- C++實(shí)現(xiàn)一個(gè)簡(jiǎn)單的線程池的示例代碼
- C++線程池實(shí)現(xiàn)代碼
- C/C++ 原生API實(shí)現(xiàn)線程池的方法
- C++11 簡(jiǎn)單實(shí)現(xiàn)線程池的方法
- C++實(shí)現(xiàn)線程池的簡(jiǎn)單方法示例
- 深入解析C++編程中線程池的使用
- c++實(shí)現(xiàn)簡(jiǎn)單的線程池
- c++線程池實(shí)現(xiàn)方法
- C++線程池實(shí)現(xiàn)
相關(guān)文章
C語(yǔ)言項(xiàng)目小學(xué)生數(shù)學(xué)考試系統(tǒng)參考
今天小編就為大家分享一篇關(guān)于C語(yǔ)言項(xiàng)目小學(xué)生數(shù)學(xué)考試系統(tǒng)參考,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-02-02C++調(diào)用Go方法的字符串傳遞問(wèn)題及解決方案
這篇文章主要介紹了C++調(diào)用Go方法的字符串傳遞問(wèn)題及解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11C語(yǔ)言實(shí)現(xiàn)小學(xué)生隨機(jī)出題測(cè)試計(jì)分
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)小學(xué)生隨機(jī)出題測(cè)試計(jì)分,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-03-03C語(yǔ)言中的字符串?dāng)?shù)據(jù)在C中的存儲(chǔ)方式
這篇文章主要介紹了C語(yǔ)言中的字符串?dāng)?shù)據(jù)在C中的存儲(chǔ)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07C語(yǔ)言實(shí)現(xiàn)電腦關(guān)機(jī)程序
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)電腦關(guān)機(jī)程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-02-02