muduo库里面的线程池是固定线程池,即创建的线程池里面的线程个数是一定的,不是动态的。线程池里面一般要包含线程队列还有任务队列,外部程序将任务存放到线程池的任务队列中,线程池中的线程队列执行任务,也是一种生产者和消费者模型。muduo库中的线程池源码如下:

线程池头文件ThreadPool.h

//线程池
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com) #ifndef MUDUO_BASE_THREADPOOL_H
#define MUDUO_BASE_THREADPOOL_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);
//关闭线程池
void stop();
//运行任务,往线程池当中的任务队列添加任务
void run(const Task& f); private:
//线程池当中的线程要执行的函数
void runInThread();
//获取任务
Task take(); MutexLock mutex_;//和条件变量配合使用的互斥锁
Condition cond_;//条件变量用来唤醒线程池中的线程队列来执行任务
string name_;//线程池名称
boost::ptr_vector<muduo::Thread> threads_;//存放线程指针
std::deque<Task> queue_;//任务队列
bool running_;//线程池是否处于运行的状态
}; } #endif

线程池实现文件ThreadPool.cc

// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com) #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());//断言当前线程池为空
running_ = true;//置线程池处于运行的状态
threads_.reserve(numThreads);//预留这么多个空间
for (int i = 0; i < numThreads; ++i)
{//for循环创建线程
char id[32];
//线程号
snprintf(id, sizeof id, "%d", i);
//创建线程并存放线程指针,绑定的函数为runInThread
threads_.push_back(new muduo::Thread(boost::bind(&ThreadPool::runInThread, this), name_+id));
threads_[i].start();//启动线程,即runInThread函数执行
}
}
//关闭线程池
void ThreadPool::stop()
{
{
MutexLockGuard lock(mutex_);
running_ = false;//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_);
// always use a while-loop, due to spurious wakeup
//如果队列为空并且处于运行的状态
while (queue_.empty() && running_)
{
cond_.wait();//等待
}
Task 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
}
}

下面是测试代码:

ThreadPool_test.cc

//线程池测试代码
#include <muduo/base/ThreadPool.h>
#include <muduo/base/CountDownLatch.h>
#include <muduo/base/CurrentThread.h> #include <boost/bind.hpp>
#include <stdio.h> void print()
{//简单地打印tid
printf("tid=%d\n", muduo::CurrentThread::tid());
} void printString(const std::string& str)
{
printf("tid=%d, str=%s\n", muduo::CurrentThread::tid(), str.c_str());
} int main()
{//创建一个线程池
muduo::ThreadPool pool("MainThreadPool");
//5个线程的线程池
pool.start(5);
//添加了2个任务运行print
pool.run(print);
pool.run(print);
//添加了100个任务
for (int i = 0; i < 100; ++i)
{
char buf[32];
snprintf(buf, sizeof buf, "task %d", i);
//绑定的函数是带参数的
pool.run(boost::bind(printString, std::string(buf)));
}
//创建CountDownLatch对象,计数值count =1,只需执行一个countDown
muduo::CountDownLatch latch(1);
//添加一个任务
pool.run(boost::bind(&muduo::CountDownLatch::countDown, &latch));
//count不为0的时候一直等待
latch.wait();
//关闭线程池
pool.stop();
}

执行结果如下:

最新文章

  1. EntityFramework中的DbContext使用疑点说明
  2. 佳能6d 魔灯
  3. failed to load session &quot;ubuntu&quot;
  4. ajax简单后台交互-我们到底能走多远系列(28)
  5. Spring MVC体系结构
  6. jquery跳出当前的each循环
  7. td
  8. pomelo源代码分析(一)
  9. AVR文章7课时:动态数字化控制
  10. 生成SQL脚本的方法
  11. 34、锁问题与线程queue
  12. 【Vue】动态加载Html片段
  13. mysql8 安装笔记
  14. Day19-File操作-创建 删除,文件过滤
  15. 报错:System.Data.Entity.Validation.DbEntityValidationException: 对一个或多个实体的验证失败
  16. SPFA穿越虫洞——负权回路得判断
  17. Codeforces 225C Barcode(矩阵上DP)
  18. centos shell基础 alias 变量单引号 双引号 history 错误重定向 2&gt;&amp;1 jobs 环境变量 .bash_history source配置文件 nohup &amp; 后台运行 cut,sort,wc ,uniq ,tee ,tr ,split, paste cat&gt; 2.txt &lt;&lt;EOF 通配符 glob模式 发邮件命令mail 2015-4-8 第十二节课
  19. Docker实战(五)编写Dockerfile
  20. 数据安全之MD5、SHA-1、CRC32区别

热门文章

  1. linux中忘记了mysql的root用户的密码怎么办?
  2. Flask入门 之 endpoint
  3. 29 collection 集合体系结构
  4. springboot web项目创建及自动配置分析(thymeleaf+flyway)
  5. "五号标题"组件:&lt;h5&gt; —— 快应用组件库H-UI
  6. python3(十二)functional
  7. app扫描二维码登陆
  8. coding++:Spring 中的 AOP 原理
  9. shell-function 删除目录和文件
  10. php-fpm 进程数的设定