画图理解
线程池其实也是一种生产者消费者模型。
何为线程池,其实就是在程序运行期间提前申请一批线程在自己的栈中等待任务的到来。
将任务投入到线程池中,在线程池中让其中一个线程完成任务。
为了让线程池中不让线程闲置着,一般可能会有多个执行流向同一个线程池发送任务,那么就必须需要一个缓冲区来存放任务,提高效率。
提前申请一批线程当消费者,对这批线程进行封装,我们就叫做线程池。
代码:
Thread.hpp,对线程封装代码
#pragma once
#include <iostream>
#include <pthread.h>
using namespace std;
typedef void*(*func_t)(void*);
struct ThreadData
{
ThreadData(const std::string&name,void*ages=nullptr)
:_name(name)
,_ages(ages)
{}
std::string _name;
void* _ages;
};
class Thread
{
public:
Thread(func_t run_func,std::string name,void*ages)
:_run_func(run_func)
,_TData(new ThreadData(name,ages))
{}
~Thread()
{}
void run_thread()
{
pthread_create(&_tid,nullptr,_run_func,(void*)_TData);
}
void join_thread()
{
pthread_join(_tid,nullptr);
}
private:
pthread_t _tid;
func_t _run_func;
ThreadData*_TData;
};
ThreadPool.hpp:线程池代码
#pragma once
#include "Thread.hpp"
#include <semaphore.h>
#include <vector>
#include <queue>
#include <unistd.h>
class auto_lock
{
public:
auto_lock(pthread_mutex_t *lock) : _lock(lock)
{
pthread_mutex_lock(_lock);
}
~auto_lock()
{
pthread_mutex_unlock(_lock);
}
private:
pthread_mutex_t *_lock;
};
template <typename Ty, size_t Num = 3>
class ThreadPool
{
private:
std::vector<Thread *> *_pool;
std::queue<Ty> *_queue_exe;
std::queue<Ty> *_queue_st;
pthread_mutex_t *_detect_lock;
pthread_mutex_t *_pthreads_lock;
pthread_cond_t *_cond;
pthread_cond_t *_swap_cond;
pthread_t *_detect_tid;
public:
bool queue_empty()
{
return _queue_exe->empty();
}
bool queue_all_empty()
{
return _queue_exe->empty()&&_queue_st->empty();
}
void signal_wait()
{
pthread_cond_wait(_cond, _detect_lock);
}
void signal_send()
{
pthread_cond_signal(_cond);
}
void signal_wait_swap()
{
pthread_cond_wait(_swap_cond, _pthreads_lock);
}
void signal_send_swap()
{
pthread_cond_signal(_swap_cond);
}
pthread_mutex_t *detect_lock()
{
return _detect_lock;
}
pthread_mutex_t *pthreads_lock()
{
return _pthreads_lock;
}
Ty get_task()
{
Ty task;
task =_queue_exe->front();
_queue_exe->pop();
return task;
}
ThreadPool()
: _pool(new std::vector<Thread *>)
, _detect_lock(new pthread_mutex_t)
, _pthreads_lock(new pthread_mutex_t)
, _cond(new pthread_cond_t)
, _swap_cond(new pthread_cond_t)
, _queue_exe(new std::queue<Ty>)
, _queue_st(new std::queue<Ty>)
, _detect_tid(new pthread_t)
{
pthread_mutex_init(_detect_lock, nullptr);
pthread_mutex_init(_pthreads_lock, nullptr);
pthread_cond_init(_swap_cond, nullptr);
pthread_cond_init(_cond, nullptr);
for (int i = 0; i < Num; ++i)
{
std::string name = "thread_";
name += std::to_string(i + 1);
_pool->push_back(new Thread(TRFunc, name, (void *)this));
}
}
~ThreadPool()
{
pthread_mutex_destroy(_detect_lock);
pthread_mutex_destroy(_pthreads_lock);
pthread_cond_destroy(_swap_cond);
pthread_cond_destroy(_cond);
for (int i = 0; i < Num; ++i)
{
_pool->at(i)->join_thread();
}
}
void RunAllThread()
{
for (int i = 0; i < Num; ++i)
{
std::cout << "线程启动!!" << std::endl;
_pool->at(i)->run_thread();
}
pthread_create(_detect_tid,nullptr,detect,this);
cout<<"Start the reconnaissance thread"<<endl;
}
static void *TRFunc(void *ages)
{
ThreadData *TData = (ThreadData *)ages;
ThreadPool<Ty> *TPool = (ThreadPool<Ty> *)TData->_ages;
while (1)
{
sleep(1);
Ty task;
{
//cout<<"debug 1"<<endl;
auto_lock lock(TPool->pthreads_lock());
// cout<<"debug 2"<<endl;
while (TPool->queue_empty())
{
//cout<<"debug 3"<<endl;
TPool->signal_wait_swap();
//cout<<"debug 4"<<endl;
}
//cout<<"debug 5"<<endl;
task=TPool->get_task();
//cout<<"debug 6"<<endl;
}
task();
}
}
void push_task(const Ty &task)
{
auto_lock lock(detect_lock());
_queue_st->push(task);
signal_send();
}
static void*detect(void*ags)
{
ThreadPool<Ty> *TPool = (ThreadPool<Ty> *)ags;
while(1)
{
if(TPool->queue_empty())//不会放数据到exe队列中,为空的时候是一定为空的,不会改变的。
{
auto_lock lock(TPool->detect_lock());
if(TPool->queue_all_empty())
{
TPool->signal_wait();
}
TPool->swap();
cout<<"debug swap~~~~~~~~~~~"<<endl;
TPool->signal_send_swap();
}
}
}
void swap()
{
std::swap(_queue_exe,_queue_st);
}
void size()
{
cout<<"_queue_exe size:"<<_queue_exe->size()<<" ";
printf("%p ",_queue_exe);
cout<<"_queue_st size:"<<_queue_st->size();
printf("%p \n",_queue_st);
}
};
主函数代码:单生产者
#include "ThreadPool.hpp"
#include <functional>
#include <memory>
class Task
{
public:
typedef std::function<int(int,int)> func_t;
Task(){}
Task(int x,int y,func_t func)
:_x(x)
,_y(y)
,_func(func)
{}
void operator ()()
{
std::cout<<"thread id:"<<pthread_self()<<" ";
std::cout<<_x<<"+"<<_y<<"="<< _func(_x,_y)<<std::endl;
}
private:
int _x;
int _y;
Task::func_t _func;
};
int main()
{
using namespace std;
ThreadPool<Task,1> p;
p.RunAllThread();
int cnt=0;
while(1)
{
int x=rand()%20;
int y=rand()%30;
Task task(x,y,[](int x,int y)->int {
return x+y;
});
p.size();
p.push_task(task);
if(cnt++%3==0)
{
sleep(1);
}
}
return 0;
}