线程池实战案例
#include<iostream>
#include<queue>
#include<pthread.h>
#include<unistd.h>
using namespace std;
typedef void (*task_func_t)(void*);
typedef void* task_arg_t;
//任务类
class Task{
task_func_t pfunc; //任务函数
task_arg_t parg; //任务参数
public:
Task(task_func_t func,task_arg_t arg):pfunc(func),parg(arg){}
void Execute()const{
pfunc(parg);
}
};
//线程池
class ThreadPool{
queue<Task> tasks;//任务队列
pthread_t tids[6];//线程集合
pthread_mutex_t mutex;//互斥量
pthread_cond_t cond;//条件变量
bool shutdown;
//添加一个新任务,把一个线程叫醒
//线程池退出时,叫醒所有线程并退出
public:
ThreadPool():shutdown(false){
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
for(auto& tid:tids){
pthread_create(&tid,NULL,(void*(*)(void*))&ThreadPool::routine,this);//强转为函数指针类型
}
}
ThreadPool(const ThreadPool&) = delete;
ThreadPool& operator=(const ThreadPool&) = delete;
~ThreadPool(){
shutdown = true;//需要结束线程时将其置为true
pthread_cond_broadcast(&cond);//这里叫醒所有线程来结束它
for(auto tid:tids){
pthread_join(tid,NULL);
}
void AddTask(task_func_t func,task_arg_t arg){
pthread_mutex_lock(&mutex);
tasks.push(Task(func,arg));
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);//添加一个任务后,唤醒一个线程
}
static void* routine(void* arg){//线程执行任务函数
ThreadPool* pool = (ThreadPool*)arg;
for(;;){
pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock,&pool->mutex);//如果底下有线程退出,这里会收到信号释放锁
pthread_mutex_lock(&pool->mutex);
while(!pool->shutdown && pool->tasks.empty()){
pthread_cond_wait(&pool->cond,&pool->mutex);//无任务时,等待派发任务将线程阻塞,等待信号并释放锁
}
if(pool->shutdown && pool->tasks.empty()){
pthread_exit(NULL); //线程退出
}
Task task = pool->tasks.front();
pool->tasks.pop();
pthread_mutex_unlock(&pool->mutex);
task.Execute();
pthread_cleanup_pop(0);
}
}
};
void test(void* arg){
cout << pthread_self() << ":" << (char*)arg << endl;
}
int main(){
Task t(test,(task_arg_t)"Hello World");
t.Execute();
ThreadPool pool;
pool.AddTask(test,(task_arg_t)"Hello1");
pool.AddTask(test,(task_arg_t)"Hello2");
pool.AddTask(test,(task_arg_t)"Hello3");
pool.AddTask(test,(task_arg_t)"Hello4");
pool.AddTask(test,(task_arg_t)"Hello5");
pool.AddTask(test,(task_arg_t)"Hello6");
pool.AddTask(test,(task_arg_t)"Hello7");
pool.AddTask(test,(task_arg_t)"Hello8");
}
c++11实现:
#include <iostream>
#include <thread>
#include <mutex>
#include <queue>
#include <functional> //function
#include <condition_variable>
using namespace std;
class ThreadPool{
typedef void (*task_func_t)(void*);
typedef void* task_arg_t;
queue<pair<task_func_t,task_arg_t>> tasks;// 任务队列
vector<thread> threads;// 线程集合
mutex m;
condition_variable cv;
bool shundown;
public:
ThreadPool(int thread_num):shundown(false){
for(int i=0;i<thread_num;++i){
threads.push_back(thread([this]{ // routine
while(true){
// pair<task_func_t,task_arg_t> task;
task_func_t func = nullptr;
task_arg_t arg = nullptr;
{
unique_lock<mutex> lock(m);
cv.wait(lock,[this]{return shundown || !tasks.empty();});
if(shundown && tasks.empty()){
break;
}
// task = tasks.front();
// func = task.first;
// arg = tasks.second;
tie(func,arg) = tasks.front();
tasks.pop();
}
func(arg);
//task.first(task.second);
}
}));
}
}
ThreadPool(const ThreadPool&) = delete;
ThreadPool& operator=(const ThreadPool&) = delete;
~ThreadPool(){
shundown = true;
cv.notify_all();
for(auto& thread:threads){
thread.join();
}
}
void AddTask(task_func_t func,task_arg_t arg){
unique_lock<mutex> lock(m);
//tasks.push(pair<task_func_t,task_arg_t>(func,arg));
//tasks.push(make_pair(func,arg));
//tasks.push({func,arg}); // C++11
tasks.emplace(func,arg); // C++11
cv.notify_one();
}
};
template <typename T,typename S>
pair<T,S> make_pair(T& a,S& b){
return pair<T,S>(a,b);
}
struct Data{
mutex m;
int n;
};
void func(void* n){
Data* d = (Data*)n;
{
unique_lock<mutex> lock(d->m);
cout<< this_thread::get_id() << ":" <<++(d->n) << endl;
}
this_thread::sleep_for(100ms);
}
struct Functor{
void operator()(void* n){
func(n);
}
};
int main(){
// 函数指针、lamdba表达式、函数对象统称为可调用对象(callable object)
function<void(void*)> pf = func;
function<void(void*)> lamdba = [](void* n){ func(n);};
function<void(void*)> functor = Functor();
Data data;
data.n = 0;
pf(&data);
lamdba(&data);
functor(&data);
return 0;
ThreadPool pool(4);
this_thread::sleep_for(100ms);
for(int i=0;i<10;++i){
pool.AddTask(func,&data);
}
}
c++11实现(改进版):
#include <iostream>
#include <thread>
#include <mutex>
#include <queue>
#include <functional> //function
#include <condition_variable>
using namespace std;
class ThreadPool{
// typedef void (*task_func_t)(void*);
typedef function<void(void*)> task_func_t;
typedef void* task_arg_t;
queue<pair<task_func_t,task_arg_t>> tasks;// 任务队列
vector<thread> threads;// 线程集合
mutex m;
condition_variable cv;
bool shundown;
public:
void routine(){
while(true){
// pair<task_func_t,task_arg_t> task;
task_func_t func = nullptr;
task_arg_t arg = nullptr;
{
unique_lock<mutex> lock(m);
cv.wait(lock,[this]{return shundown || !tasks.empty();});
if(shundown && tasks.empty()){
break;
}
// task = tasks.front();
// func = task.first;
// arg = tasks.second;
tie(func,arg) = tasks.front();
tasks.pop();
}
func(arg);
//task.first(task.second);
}
}
ThreadPool(int thread_num):shundown(false){
for(int i=0;i<thread_num;++i){
threads.push_back(thread([this]{ // routine
routine();
}));
}
}
ThreadPool(const ThreadPool&) = delete;
ThreadPool& operator=(const ThreadPool&) = delete;
~ThreadPool(){
shundown = true;
cv.notify_all();
for(auto& thread:threads){
thread.join();
}
}
void AddTask(task_func_t func,task_arg_t arg){
unique_lock<mutex> lock(m);
//tasks.push(pair<task_func_t,task_arg_t>(func,arg));
//tasks.push(make_pair(func,arg));
//tasks.push({func,arg}); // C++11
tasks.emplace(func,arg); // C++11
cv.notify_one();
}
};
template <typename T,typename S>
pair<T,S> make_pair(T& a,S& b){
return pair<T,S>(a,b);
}
struct Data{
mutex m;
int n;
};
void func(void* n){
Data* d = (Data*)n;
{
unique_lock<mutex> lock(d->m);
cout<< this_thread::get_id() << ":" <<++(d->n) << endl;
}
this_thread::sleep_for(100ms);
}
struct Functor{
void operator()(void* n){
func(n);
}
};
int main(){
/*
// 函数指针、lamdba表达式、函数对象统称为可调用对象(callable object)
function<void(void*)> pf = func;
function<void(void*)> lamdba = [](void* n){ func(n);};
function<void(void*)> functor = Functor();
pf(&data);
lamdba(&data);
functor(&data);
return 0;
*/
Data data;
data.n = 0;
ThreadPool pool(4);
this_thread::sleep_for(100ms);
for(int i=0;i<10;++i){
pool.AddTask([](void*n){func(n);},&data);
}
}