muduo源码学习(8)-ThreadPool

来源:互联网 发布:淘宝联盟怎么合并购买 编辑:程序博客网 时间:2024/06/05 17:18

多线程可以提高效率,当由于资源限制,不可能创建大量的线程,与CPU核数有关,而且,当处理任务是,临时的创建线程,销毁线程比较费时,比较理想的做法是实现创建一定数量的线程,然后线程不断的接受任务,在线程中处理任务,这就是线程池,java类库中有线程池,c++需要自己封装,muduo中就通过了线程池类。线程池本质上还是生产者消费者模型。线程池类中有一个任务队列,工作线程不断的消费任务,生产者添加任务。

在base/ThreadPool.h中

class ThreadPool : boost::noncopyable{ public: //任务  typedef boost::function<void ()> Task;  explicit ThreadPool(const string& name = string());  ~ThreadPool();  void start(int numThreads);  void stop();  void run(const Task& f); private:  void runInThread();  Task take();  MutexLock mutex_;  Condition cond_;  string name_;    //存放Thread *  boost::ptr_vector<muduo::Thread> threads_;    //任务队列  std::deque<Task> queue_;  //是否在运行  bool running_;};
主要成员就是一个队列,条件变量,锁,threads_存放Thread *指针


base/ThreadPool.cc

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());  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_ = false;  //  cond_.notifyAll();  }/调用join()  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_);  // always use a while-loop, due to spurious wakeup  while (queue_.empty() && running_)  {    cond_.wait();  }  Task task;  if(!queue_.empty())  {    task = queue_.front();    queue_.pop_front();  }  return task;}//工作线程中调用void ThreadPool::runInThread(){  try  {      while (running_)    {    //获取任务      Task task(take());      if (task)      {      //调用任务        task();      }    }  }  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  }}

维护了一个线程安全的任务队列,启动线程池后,工作线程不断的调用take()获取任务,如果没有任务,可能会等待,之后调用任务函数。在析构函数中,调用stop(),唤醒所有可能阻塞在take()的线程,此时runing为false,循环结束,线程结束。