C++线程池

#pragma once
#include<queue>
#include<pthread.h>
using namespace std;

using callback =void(*)(void* arg);

//task struct
template<typename T>
struct Task{
Task(){
    function =nullptr;
    arg=nullptr;
}
Task(callback f,void* arg){
    this->arg=(T*)arg;
    function=f;
}
void (*function)(void* arg);
T* arg;
};
template<typename T> 
class TaskQueue{
public:
TaskQueue();
~TaskQueue();

//add  task
void addTask(Task<T> task);
void addTask(callback f,void* arg);
//out a task
Task<T> takeTask();

inline int taskNumber(){
    return m_taskQ.size();
}

private:
pthread_mutex_t m_mutex;
std::queue<Task<T>> m_taskQ;

};

#include "TaskQueue.h"

template<typename T> 
TaskQueue<T>::TaskQueue(){
pthread_mutex_init(&m_mutex,NULL);
}

template<typename T> 
TaskQueue<T>::~TaskQueue(){
pthread_mutex_destroy(&m_mutex);
}

template<typename T> 
void TaskQueue<T>::addTask(Task<T> task){
pthread_mutex_lock(&m_mutex);
m_taskQ.push(task);
pthread_mutex_unlock(&m_mutex);
}

template<typename T> 
void TaskQueue<T>::addTask(callback f,void* arg){
pthread_mutex_lock(&m_mutex);
m_taskQ.push(Task<T>(f,arg));
pthread_mutex_unlock(&m_mutex);
}

template<typename T> 
Task<T> TaskQueue<T>::takeTask(){
    Task<T> t;
pthread_mutex_lock(&m_mutex);
if(!m_taskQ.empty()){
    t=m_taskQ.front();
    m_taskQ.pop();
}
pthread_mutex_unlock(&m_mutex);
return t;
}



#pragma once
#include "TaskQueue.h"
#include<pthread.h>

template<typename T> 
class ThreadPool{
public:
ThreadPool(int min,int max);
~ThreadPool();
//add task to thread pool
void addTask(Task<T> task);
int getbusyNum();
int getliveNum();

private:
//working thread
static void* worker(void *arg);
static void* manager(void *arg);
//onr thread exit
void threadExit();

//task queue
TaskQueue<T>* m_taskQ;

pthread_t managerID;//manager
pthread_t *threadIDs;//work thread num
int minNum;//minnum thread num
int maxNum;//maxnum thread num
int liveNum;//live thread num
int busyNum;//busy thread num
int exitNum;//going to destroy thread num

pthread_mutex_t mutexPool;//desttroy the threadpool
pthread_cond_t notempty;//the task queue is null?

bool shutdown;//destroy thre threadpool

};
#include "ThreadPool.h"
#include <iostream>
#include<string.h>//c memset
#include<string>//string lei
#include <unistd.h>
#include<pthread.h>
using namespace std;

template<typename  T>
ThreadPool<T>::ThreadPool(int min,int max){
//shilihua task queue
m_taskQ=new TaskQueue<T>;
do{
if(m_taskQ==nullptr){
cout<<"malloc taskQ fail..."<<endl;
return;
}
//alloc memory
threadIDs=new pthread_t[max];
if(threadIDs==nullptr){
cout<<"malloc threadIDs fail..."<<endl;
return;
}//if

//two locks
if (pthread_mutex_init(&mutexPool, NULL) != 0 ||
            pthread_cond_init(&notempty, NULL) != 0)
        {
            cout << "init mutex or condition fail..." << endl;
            break;
        }

memset(threadIDs,0,sizeof(pthread_t)*max);
minNum=min;
maxNum=max;
busyNum=0;
liveNum=min;
exitNum=0;
shutdown=false;
//create manager thread
pthread_create(&managerID,NULL,manager,this);

//create minnum thread
for(int i=0;i<min;++i){
pthread_create(&threadIDs[i],NULL,worker,this);
}
}while(0);

}

template<typename  T>
ThreadPool<T>::~ThreadPool(){
shutdown=true;
//destory manager thread
pthread_join(managerID,NULL);
//alive all the consumer thread
for(int i=0;i<liveNum;i++)
pthread_cond_signal(&notempty);

if(m_taskQ) delete m_taskQ;
if(threadIDs) delete[]threadIDs;

pthread_mutex_destroy(&mutexPool);
pthread_cond_destroy(&notempty);
}

template<typename  T>
void ThreadPool<T>::addTask(Task<T> task){
if(shutdown) return;
m_taskQ->addTask(task);
pthread_cond_signal(&notempty);
}


template<typename  T>
int ThreadPool<T>::getliveNum(){
int threadNum=0;
pthread_mutex_lock(&mutexPool);
threadNum=liveNum;
pthread_mutex_unlock(&mutexPool);
return threadNum;
}

template<typename  T>
int ThreadPool<T>::getbusyNum(){
int busyNum=0;
pthread_mutex_lock(&mutexPool);
busyNum=busyNum;
pthread_mutex_unlock(&mutexPool);
return busyNum;
}

template<typename  T>
void* ThreadPool<T>::worker(void* arg){
ThreadPool *pool=static_cast<ThreadPool*>(arg);
//always working
while(true){

pthread_mutex_lock(&pool->mutexPool);
//task queue is null,but the threadpool dont shutdown
while(pool->m_taskQ->taskNumber()==0&&!pool->shutdown){
//block all the thread
pthread_cond_wait(&pool->notempty,&pool->mutexPool);
if(pool->exitNum>0){
pool->exitNum--;
if(pool->liveNum>pool->minNum){
    pool->liveNum--;
    pthread_mutex_unlock(&pool->mutexPool);
    pool->threadExit();
}
}//if
}//while

if(pool->shutdown){
    pthread_mutex_unlock(&pool->mutexPool);
    pool->threadExit();
}

Task<T> task=pool->m_taskQ->takeTask();
pool->busyNum++;

pthread_mutex_unlock(&pool->mutexPool);
cout << "thread " << to_string(pthread_self()) << " start working..." << endl;
task.function(task.arg);
delete task.arg;
task.arg = nullptr;

//task is over
cout << "thread " << to_string(pthread_self()) << " end working..."<<endl;
pthread_mutex_lock(&pool->mutexPool);
pool->busyNum--;
pthread_mutex_unlock(&pool->mutexPool);
}//while
return nullptr;
}

template<typename  T>
void* ThreadPool<T>::manager(void* arg){
ThreadPool* pool=static_cast<ThreadPool*>(arg);

while(!pool->shutdown){
sleep(5);

pthread_mutex_lock(&pool->mutexPool);
int queuesize=pool->m_taskQ->taskNumber();
int liveNum=pool->liveNum;
int busyNum=pool->busyNum;
pthread_mutex_unlock(&pool->mutexPool);

const int number=2;
if(queuesize>liveNum-busyNum&&liveNum<pool->maxNum){
pthread_mutex_lock(&pool->mutexPool);
int num=0;
for(int i=0;i<pool->maxNum&&num<number&&pool->liveNum<pool->maxNum;i++)
{
if(pool->threadIDs[i]==0){
pthread_create(&pool->threadIDs[i],NULL,worker,pool);
num++;
pool->liveNum++;
}

}
pthread_mutex_unlock(&pool->mutexPool);



}//if

if(busyNum*2<liveNum&&liveNum>pool->minNum){
pthread_mutex_lock(&pool->mutexPool);
pool->exitNum=number;
pthread_mutex_unlock(&pool->mutexPool);
for(int i=0;i<number;i++)
pthread_cond_signal(&pool->notempty);

}

}
return nullptr;
}

template<typename  T>
void ThreadPool<T>::threadExit(){
    pthread_t tid=pthread_self();
for(int i=0;i<maxNum;i++)
{
if(threadIDs[i]==tid){
cout<<"threadExit() function:called"<<
to_string(pthread_self())<<"exiting ..."<<endl;
threadIDs[i]=0;
break;
}
    }
    pthread_exit(NULL);
}

C++线程池可以用来处理一些需要并发执行的任务,同时避免频繁创建和销毁线程所带来的开销。下面是一个简单的C++线程池实现: ```cpp #include <iostream> #include <queue> #include <thread> #include <mutex> #include <condition_variable> class ThreadPool { public: ThreadPool(size_t num_threads) { for (size_t i = 0; i < num_threads; ++i) { threads_.emplace_back([this] { while (true) { Task task; { std::unique_lock<std::mutex> lock(mutex_); cond_.wait(lock, [this] { return !tasks_.empty() || stop_; }); if (stop_ && tasks_.empty()) return; task = std::move(tasks_.front()); tasks_.pop(); } task(); } }); } } ~ThreadPool() { { std::unique_lock<std::mutex> lock(mutex_); stop_ = true; } cond_.notify_all(); for (auto& thread : threads_) { thread.join(); } } template <typename Func, typename... Args> void AddTask(Func&& func, Args&&... args) { auto task = std::bind(std::forward<Func>(func), std::forward<Args>(args)...); { std::unique_lock<std::mutex> lock(mutex_); tasks_.emplace(std::move(task)); } cond_.notify_one(); } private: using Task = std::function<void()>; std::vector<std::thread> threads_; std::queue<Task> tasks_; std::mutex mutex_; std::condition_variable cond_; bool stop_ = false; }; ``` 这个实现定义了一个ThreadPool类,构造函数中创建了指定数量的线程,并且每个线程都会从任务队列中获取任务并执行;析构函数中会通知所有线程停止执行,并等待所有线程退出;AddTask方法用于添加一个任务到任务队列中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值