C++实现一个简易的线程池
文章目錄
- 線程池的概念
- 什么是線程池
- 線程池的優(yōu)點(diǎn)
- 線程池的應(yīng)用場景
- 線程池的實(shí)現(xiàn)
- 實(shí)現(xiàn)思路
- 代碼實(shí)現(xiàn)
線程池的概念
什么是線程池
顧名思義,線程池就是一個(gè)有很多空閑線程的池子(線程的數(shù)量受到限制),需要用到多執(zhí)行流進(jìn)行任務(wù)處理時(shí),就從池子中喚醒一個(gè)線程去處理任務(wù)
線程池的優(yōu)點(diǎn)
- 避免大量線程頻繁創(chuàng)建和銷毀帶來的時(shí)間成本
:如果在一開始即創(chuàng)建好線程,要用的時(shí)候直接從線程池中取出,用完再放回,這樣就大大減少了創(chuàng)建與銷毀帶來的時(shí)間成本 - 避免無限制的線程創(chuàng)建導(dǎo)致資源耗盡
:線程池限制了線程的數(shù)量,這樣就保證了不會因?yàn)榫€程創(chuàng)建過多導(dǎo)致資源耗竭,程序崩潰的情況
線程池的應(yīng)用場景
有大量的數(shù)據(jù)處理請求,需要多執(zhí)行流并發(fā)/并行處理
線程池的實(shí)現(xiàn)
實(shí)現(xiàn)思路
首先線程池的核心,就是大量的線程和一個(gè)任務(wù)緩沖隊(duì)列。在線程池創(chuàng)建時(shí)就提前創(chuàng)建好一定數(shù)量的線程,如果有任務(wù)到來則將任務(wù)放入緩沖隊(duì)列中,此時(shí)喚醒線程池中的線程取出任務(wù)進(jìn)行處理,如果線程池沒有空閑線程,則阻塞任務(wù),直到有線程處理完任務(wù)回歸線程池中。同時(shí),因?yàn)椴煌蝿?wù)有不同的處理方法,所以要開放接口給外界,處理的數(shù)據(jù)和方法由外界自己定,線程池只負(fù)責(zé)調(diào)用對應(yīng)的任務(wù)處理方法進(jìn)行處理,不關(guān)心其中的內(nèi)容。這樣就更具有靈活性。
代碼實(shí)現(xiàn)
下面就來實(shí)現(xiàn)一個(gè)線程池,具體的細(xì)節(jié)都有注釋
#include<iostream> #include<pthread.h> #include<cstdlib> #include<queue>//類型重命名,將處理的方法定義為一個(gè)函數(shù)指針 typedef void (*handler_t)(int);const size_t MAX_SIZE = 10;//任務(wù) class ThreadTask {public://設(shè)置需要處理的數(shù)據(jù)與對應(yīng)的處理方法void SetTask(int data, handler_t handler){_data = data;_handler = handler;}//處理數(shù)據(jù)void Run(){_handler(_data);}private:int _data;handler_t _handler; };//線程池 class ThreadPool {public:ThreadPool(size_t capacity = MAX_SIZE) : _capacity(capacity){pthread_cond_init(&_cond, NULL);pthread_mutex_init(&_mutex, NULL);//線程池提前創(chuàng)建線程for(size_t i = 0; i < _capacity; i++){pthread_t pid;int ret = pthread_create(&pid, NULL, start_routine, this);if(ret){std::cout << "線程創(chuàng)建失敗" << std::endl;exit(-1);}}}~ThreadPool(){pthread_cond_destroy(&_cond);pthread_mutex_destroy(&_mutex);}void Push(ThreadTask& Task){//互斥鎖保證線程安全pthread_mutex_lock(&_mutex);//將任務(wù)放入隊(duì)列中_queue.push(Task);pthread_mutex_unlock(&_mutex);//喚醒線程池全部線程,誰搶到誰就來處理這個(gè)任務(wù)pthread_cond_broadcast(&_cond);}//入口函數(shù)的參數(shù)只能有一個(gè)void*,所以需要寫為static函數(shù)來去掉隱含的this指針static void* start_routine(void *arg){//將void*強(qiáng)轉(zhuǎn)為需要的類型ThreadPool* pool = (ThreadPool*)arg;while(1){pthread_mutex_lock(&pool->_mutex); //如果任務(wù)隊(duì)列為空則使線程循環(huán)等待while(pool->_queue.empty()){pthread_cond_wait(&pool->_cond, &pool->_mutex);}ThreadTask Task;//將任務(wù)出隊(duì)進(jìn)行處理Task = pool->_queue.front();pool->_queue.pop();pthread_mutex_unlock(&pool->_mutex);//解鎖后再處理,因?yàn)榧渔i只是保證隊(duì)列操作的安全性Task.Run();}return NULL;}private://互斥鎖保證線程安全,條件變量保證任務(wù)的提交與處理同步pthread_cond_t _cond;pthread_mutex_t _mutex;size_t _capacity;std::queue<ThreadTask> _queue; };下面寫一個(gè)函數(shù)來測試一下
#include "ThreadPool.hpp" #include<unistd.h>void handler1(int data) {std::cout << "線程ID:"<< pthread_self() <<" 處理奇數(shù)數(shù)據(jù):" << data << std::endl;sleep(1); }void handler2(int data) {std::cout << "線程ID:"<< pthread_self() <<" 處理偶數(shù)數(shù)據(jù):" << data << std::endl;sleep(1); }int main() {ThreadPool pool;for(int i = 0; i < 10; i++){ThreadTask task;//分別處理奇數(shù)和偶數(shù)if(i & 1){task.SetTask(i, handler1);}else{task.SetTask(i, handler2); }//任務(wù)放入隊(duì)列中pool.Push(task);}//休眠一段時(shí)間防止結(jié)束后主線程退出sleep(100);return 0; }使用兩種不同的處理方法來分別處理0-9的奇偶數(shù)
運(yùn)行截圖
總結(jié)
以上是生活随笔為你收集整理的C++实现一个简易的线程池的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++ STL : 模拟实现STL中的s
- 下一篇: C++ STL : 模拟实现STL中的v