C++11 簡單實現(xiàn)線程池的方法
什么是線程池
線程池是一種多線程處理形式,處理過程中將任務添加到隊列,然后在創(chuàng)建線程后自動啟動這些任務。線程池線程都是后臺線程。每個線程都使用默認的堆棧大小,以默認的優(yōu)先級運行,并處于多線程單元中。如果某個線程在托管代碼中空閑(如正在等待某個事件),則線程池將插入另一個輔助線程來使所有處理器保持繁忙。如果所有線程池線程都始終保持繁忙,但隊列中包含掛起的工作,則線程池將在一段時間后創(chuàng)建另一個輔助線程但線程的數(shù)目永遠不會超過最大值。超過最大值的線程可以排隊,但他們要等到其他線程完成后才啟動。
不使用線程池有哪些弊端
創(chuàng)建太多線程,將會浪費一定的資源,有些線程未被充分使用。
銷毀太多線程,將導致之后浪費時間再次創(chuàng)建它們。
創(chuàng)建線程太慢,將會導致長時間的等待,性能變差。
銷毀線程太慢,導致其它線程資源饑餓。
線程池的組成部分
1、線程池管理器(ThreadPoolManager):用于創(chuàng)建并管理線程池
2、工作線程(WorkThread): 線程池中線程
3、任務接口(Task):每個任務必須實現(xiàn)的接口,以供工作線程調(diào)度任務的執(zhí)行。
4、任務隊列:用于存放沒有處理的任務。提供一種緩沖機制
下面直接看代碼實現(xiàn)
ThreadPoolManage.hpp
#pragma once #include <thread> #include <vector> #include <queue> #include <condition_variable> #include <mutex> /* * 抽象一個任務 根據(jù)自己的需求擴展 */ class AbsTask { public: AbsTask() = default; virtual ~AbsTask() = default; public: virtual void run() = 0; }; template<class _Ty> class ThreadPoolManage { public: ThreadPoolManage(unsigned int nMaxThread) :mMaxThreadNum(nMaxThread) , mThreadStatus(false) { //啟動的時候就要創(chuàng)建線程 auto maxNum = std::thread::hardware_concurrency(); //獲取當前操作系統(tǒng)中CPU的核心數(shù)量 根據(jù)核心數(shù)量來設置 最大工作線程的并發(fā)數(shù)量 mMaxThreadNum = mMaxThreadNum > maxNum ? maxNum : mMaxThreadNum; //創(chuàng)建工作線程池 for (auto i = 0; i < mMaxThreadNum; i++) { mWorkers.emplace_back([this] { while (true) { std::unique_lock<std::mutex> lock(this->mQueue_mutex); this->mCondition.wait(lock, [this]() {return this->mThreadStatus || !this->mTasks.empty(); }); if (this->mThreadStatus && this->mTasks.empty()) { return; } //獲取隊列頭部的任務 auto task = std::move(this->mTasks.front()); //任務出隊 this->mTasks.pop(); //執(zhí)行工作 task.run(); } }); } } ~ThreadPoolManage() { { std::unique_lock<std::mutex> lock(this->mQueue_mutex); this->mThreadStatus = true; } //通知所有線程起來工作 然后退出 this->mCondition.notify_all(); //等待所有線程工作完畢 for (std::thread& worker : this->mWorkers) { if (worker.joinable()) { worker.join(); } } } /* * 添加任務到任務隊列 */ void addTask(_Ty& task) { std::unique_lock<std::mutex> lock(this->mQueue_mutex); if (mThreadStatus) { throw std::runtime_error("workers stop"); } mTasks.emplace(std::move(task)); mCondition.notify_one(); } private: /* * 工作線程池 */ std::vector<std::thread> mWorkers; /* * 任務隊列 */ std::queue<_Ty> mTasks; /* 工作線程的最大并發(fā)數(shù)量 */ unsigned int mMaxThreadNum; /* 條件變量 控制線程池中線程的工作狀態(tài) */ std::condition_variable mCondition; /* * 工作線程鎖 */ std::mutex mQueue_mutex; /* * 控制線程的開關 false 繼續(xù)工作 true 退出線程 */ bool mThreadStatus; };
調(diào)用代碼
main.cpp
#include <iostream> #include <chrono> #include "ThreadPool.hpp" class Task :public AbsTask { public: void run() override { std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "works ...... " << std::this_thread::get_id() << std::endl; } }; int main() { ThreadPoolManage<Task> ThreadPool(8); for (size_t i = 0; i < 256; i++) { Task task; ThreadPool.addTask(task); } std::cin.get(); system("pause"); }
到此這篇關于C++11 簡單實現(xiàn)線程池的方法的文章就介紹到這了,更多相關C++11 線程池內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C++消息隊列(定義,結構,如何創(chuàng)建,發(fā)送與接收)
這篇文章主要介紹了C++消息隊列(定義,結構,如何創(chuàng)建,發(fā)送與接收),消息隊列是一種先進先出的隊列型數(shù)據(jù)結構,實際上是系統(tǒng)內(nèi)核中的一個內(nèi)部鏈表2022-08-08C語言編程中從密碼文件獲取數(shù)據(jù)的函數(shù)總結
這篇文章主要介紹了C語言編程中從密碼文件獲取數(shù)據(jù)的函數(shù)總結,包括getpw()函數(shù)和getpwnam()函數(shù)以及getpwuid()函數(shù),需要的朋友可以參考下2015-08-08C語言實現(xiàn)十進制轉(zhuǎn)任意進制的代碼詳解
這篇文章主要介紹了C語言實現(xiàn)十進制轉(zhuǎn)任意進制,運用一個數(shù)組,通過數(shù)字每次取任意進制模,存在數(shù)組中, 再通過倒取數(shù)組中的數(shù)值,來實現(xiàn)進制轉(zhuǎn)換,如果遇到十六進制,利用ASCII碼值 數(shù)字字符和大寫字母 相差55的特性來解決,文中有詳細代碼示例,需要的朋友可以參考下2024-05-05Linux環(huán)境g++編譯GDAL動態(tài)庫操作方法
下面小編就為大家?guī)硪黄狶inux環(huán)境g++編譯GDAL動態(tài)庫操作方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-05-05