经典的C++ 线程池模型。
【ThreadPool.h】
#pragma once
#include <iostream>
#include <queue>
#include <thread>
using namespace std;
template <class T>
class ThreadPool
{
private:
int _threadCount;
queue<T> _queue;
pthread_mutex_t _mlock;
pthread_cond_t _cond;
static ThreadPool<T> *_instance;
private:
ThreadPool(int threadCount = 3)
: _threadCount(threadCount)
{
pthread_mutex_init(&_mlock,nullptr);
pthread_cond_init(&_cond,nullptr);
}
ThreadPool(const ThreadPool<T> &) = delete;
ThreadPool& operator=(const ThreadPool<T>&)=delete; //禁用拷贝构造和赋值运算符重载
void Lock()
{
pthread_mutex_lock(&_mlock);
}
void Unlock()
{
pthread_mutex_unlock(&_mlock);
}
void Pop(T *t)
{
*t = _queue.front();
_queue.pop();
}
bool Empty()
{
return _queue.empty();
}
static void *Handler(void *arg)
{
ThreadPool<T> *obj = (ThreadPool<T> *)arg;
pthread_detach(pthread_self());
while (true)
{
obj->Lock();
//先获取任务,没有任务挂起
while (obj->Empty())
{
pthread_cond_wait(&obj->_cond, &obj->_mlock);//阻塞后同时会释放_mlock
}
T t;
obj->Pop(&t);
obj->Unlock();
//处理任务
t();
}
}
void Init()
{
pthread_t tid;
for (int i = 0; i < _threadCount; i++)
{
pthread_create(&tid, nullptr, Handler, this);
}
}
public:
~ThreadPool()
{
pthread_mutex_destroy(&_mlock);
pthread_cond_destroy(&_cond);
}
static ThreadPool<T> *GetInstance()
{
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
if (_instance == nullptr)
{
pthread_mutex_lock(&mtx);
if (_instance == nullptr)
{
_instance = new ThreadPool<T>;
_instance->Init();
}
pthread_mutex_unlock(&mtx);
}
return _instance;
}
void Push(const T &t)
{
Lock();
_queue.push(t);
Unlock();
//此时可能所有的线程已经全部休眠,需要唤醒一下
pthread_cond_signal(&_cond);
}
};
template <class T>
ThreadPool<T> *ThreadPool<T>::_instance = nullptr;
【main.cpp】
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include "ThreadPool.h"
pthread_mutex_t taskMutex;
class Task
{
private:
int a;
int b;
public:
Task()
{}
Task(int x, int y)
: a(x), b(y)
{}
void operator()()
{
pthread_mutex_lock(&taskMutex);
cout<<"线程ID:"<<pthread_self()<<","<< a << "+" << b << "=" << a + b << endl;
pthread_mutex_unlock(&taskMutex);
}
};
void *Produce(void *arg)
{
pthread_detach(pthread_self());
ThreadPool<Task> *pool = (ThreadPool<Task> *)arg;
while (true)
{
Task t(rand() % 10, rand() % 10);
sleep(1);
pool->Push(t);
}
}
int main()
{
pthread_mutex_init(&taskMutex, nullptr);
srand((long long)time(nullptr));
pthread_t tid;
ThreadPool<Task> *pool = ThreadPool<Task>::GetInstance();
for (int i = 0; i < 5; i++)
{
pthread_create(&tid, nullptr, Produce, pool);
}
while (1);
return 0;
}
【Makefile】
src=$(wildcard *.cpp)
obj=$(patsubst %.cpp, %, $(src))
CFLAGS+=-std=c++11 -pthread
INC+=-I./
ALL:$(obj)
%:%.cpp
g++ $< -o $@ $(INC) $(CFLAGS)
.PHONY:clean ALL
clean:
-rm -rf $(obj)
运行结果:
这个例子用到的知识非常多,包括:类模板、单例模式、STL中的队列、条件变量、互斥锁、以及多线程等,值得细看
主要描述了,main函数创建了5个生产者线程,不断向queue中加入task。
生产者同样也有5个线程,5个线程不间断的去询问队列,是否有任务可做,如果没有,则使用pthread_cond_wait()阻塞当前线程。
pthread_cond_wait():
用于阻塞当前线程,等待别的线程使用pthread_cond_signal()
或pthread_cond_broadcast
来唤醒它 pthread_cond_wait()
必须与pthread_mutex
配套使用。pthread_cond_wait()
函数一进入wait
状态就会自动release mutex
。当其他线程通过pthread_cond_signal()
或pthread_cond_broadcast
,把该线程唤醒,使pthread_cond_wait()
通过(返回)时,该线程又自动获得该mutex
。
使用t() 去处理队列中的任务,这个是重载了()运算符。
此代码忘记在哪里看到的了,今天偶尔翻到,这里记录一下,如有侵权请聊系我删除。