线程池包括
成员变量:
一个任务队列:deque queue_,用条件变量同步
线程组:ptr_vector threads_
bool running :标志是否start启动了,或者stop 停止了
成员函数:
start:初始化线程数目
stop:停止线程池
take:从queue中获取任务
runInThread:线程执行函数 :循环 调用 take 获取任务,并执行任务
#ifndef MUDUO_BASE_THREADPOLL_H
#define MUDUO_BASE_THREADPOLL_H
#include <muduo/base/Condition.h>
#include <muduo/base/Mutex.h>
#include <muduo/base/Thread.h>
#include <muduo/base/Types.h>
#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <deque>
namespace muduo
{
class ThreadPool : boost::noncopyable
{
public:
typedef boost::function<void ()> Task;
explicit ThreadPool(const string& name = string());
~ThreadPool();
void start(int numThreads);//启动numThreads个线程
void stop();//停止线程池
void run(const Task& f);//将任务f加入线程池运行
private:
void runInThread();//线程创建时所传入的运行函数: --> take( )--> f( ) 即运行run中添加的任务f
Task take();//获取任务队列 queue_ 中的任务 即run中添加的f
MutexLock mutex_;
Condition cond_;
string name_;
boost::ptr_vector<muduo::Thread> threads_;
std::deque<Task> queue_;
bool running_;
};
}
#endif
#include <muduo/base/ThreadPool.h>
#include <muduo/base/Exception.h>
#include <boost/bind.hpp>
#include <assert.h>
#include <stdio.h>
using namespace muduo;
ThreadPool::ThreadPool(const string& name)
: mutex_(),
cond_(mutex_),
name_(name),
running_(false)
{
}
ThreadPool::~ThreadPool()
{
if(running_)
stop();
}
void ThreadPool::start(int numThreads)
{
//assert(threads_.empty());
if(!threads_.empty())
return ;
running_ = true;
threads_.reserve(numThreads);
for(int i=0;i<numThreads;i++)
{
char id[32];
snprintf(id, sizeof id, "%d", i);
threads_.push_back(new muduo::Thread(boost::bind(&ThreadPool::runInThread, this), name_+id));
threads_[i].start();
}
}
void ThreadPool::stop()
{
{
MutexLockGuard lock(mutex_);//一定要加锁!!,因为要修改running_,take()里面wait等待的条件里有running,如果不加锁保护running,take()中先执行while判断running为true,接着下面修改了running,也notifyAll了,这时take中才执行wait,那就永远锁住。
running_ = false;
cond_.notifyAll();
}
for_each(threads_.begin(), threads_.end(), boost::bind(&muduo::Thread::join, _1));//等待线程回收
}
void ThreadPool::run(const Task& task)
{
if(threads_.empty())
task();
else
{
MutexLockGuard lock(mutex_);
queue_.push_back(task);
cond_.notify();
}
}
ThreadPool::Task ThreadPool::take()
{
MutexLockGuard lock(mutex_);
//要判断running,如果stop了线程池,那就不要再wait了
while(queue_.empty() && running_)
cond_.wait();
Task task;//task=0 boost::function 可以判断是否为NULL
//一定要判断队列非空,因为可能时running为false 退出上面循环的
if(!queue_.empty())
{
task=queue_.front();
queue_.pop_front();
}
return task;
}
void ThreadPool::runInThread()
{
try
{
while(running_)
{
Task work=take();//获取任务
if(work)//要判断任务是否为空,因为stop的时候会返回空task
work();
}
}
catch(const Exception& ex)
{
fprintf(stderr, "exception caught in ThreadPool %s\n", name_.c_str());
fprintf(stderr, "reason: %s\n", ex.what());
fprintf(stderr, "stack trace: %s\n", ex. stackTrace());
abort();
}
catch (const std::exception& ex)
{
fprintf(stderr, "exception caught in ThreadPool %s\n", name_.c_str());
fprintf(stderr, "reason: %s\n", ex.what());
abort();
}
catch (...)
{
fprintf(stderr, "unknown exception caught in ThreadPool %s\n", name_.c_str());
throw; // rethrow
}
}
参考:c++教程网