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();
}

执行结果如下:

muduo网络库源码学习————线程池实现的更多相关文章

  1. muduo网络库源码学习————线程类

    muduo库里面的线程类是使用基于对象的编程思想,源码目录为muduo/base,如下所示: 线程类头文件: // Use of this source code is governed by a B ...

  2. muduo网络库源码学习————线程特定数据

    muduo库线程特定数据源码文件为ThreadLocal.h //线程本地存储 // Use of this source code is governed by a BSD-style licens ...

  3. muduo网络库源码学习————线程本地单例类封装

    muduo库中线程本地单例类封装代码是ThreadLocalSingleton.h 如下所示: //线程本地单例类封装 // Use of this source code is governed b ...

  4. muduo网络库源码学习————线程安全

    线程安全使用单例模式,保证了每次只创建单个对象,代码如下: Singleton.h // Use of this source code is governed by a BSD-style lice ...

  5. muduo网络库源码学习————Timestamp.cc

    今天开始学习陈硕先生的muduo网络库,moduo网络库得到很多好评,陈硕先生自己也说核心代码不超过5000行,所以我觉得有必要拿过来好好学习下,学习的时候在源码上面添加一些自己的注释,方便日后理解, ...

  6. muduo网络库源码学习————日志滚动

    muduo库里面的实现日志滚动有两种条件,一种是日志文件大小达到预设值,另一种是时间到达超过当天.滚动日志类的文件是LogFile.cc ,LogFile.h 代码如下: LogFile.cc #in ...

  7. muduo网络库源码学习————互斥锁

    muduo源码的互斥锁源码位于muduo/base,Mutex.h,进行了两个类的封装,在实际的使用中更常使用MutexLockGuard类,因为该类可以在析构函数中自动解锁,避免了某些情况忘记解锁. ...

  8. muduo网络库源码学习————日志类封装

    muduo库里面的日志使方法如下 这里定义了一个宏 #define LOG_INFO if (muduo::Logger::logLevel() <= muduo::Logger::INFO) ...

  9. muduo网络库源码学习————无界队列和有界队列

    muduo库里实现了两个队列模板类:无界队列为BlockingQueue.h,有界队列为BoundedBlockingQueue.h,两个测试程序实现了生产者和消费者模型.(这里以无界队列为例,有界队 ...

随机推荐

  1. 最全的中文NLP资源库,你确定不来看一下吗?

    最全的中文NLP资源库,你确定不来看一下吗? 22/100 发布文章 qq_39248703 hello,小伙伴们大家好,今天给大家分享NLP资源库,可以说是最全的资源库了,很多包非常有趣,值得收藏, ...

  2. git log查看某文件的修改历史

    1. git log filename 可以看到fileName相关的commit记录 2. git log -p filename可以显示每次提交的diff 3. 只看某次提交中的某个文件变化,可以 ...

  3. 邮件退信“Remote Server returned '420 4.2.0 Recipient deferred because there is no Mdb'”

    标题是一个近期遇到的NDR 对于Exchange运维工作者,NDR通常给了我们较为清晰的排错方向,我们先看一下退信的原因, 我的一台MailBox报错“远程服务器返回‘420 4.2.0’接受延迟,因 ...

  4. Linux中vim编辑器 的 快捷键 --- 常用 的 都比较全

    Linux中vim编辑器的功能非常强大,许多常用快捷键用起来非常方便,这里将我学vim入门时学的一些常用的快捷键分享给大家一下,希望可以帮助你们. 这个是我将鸟哥书上的进行了一下整理的,希望不要涉及到 ...

  5. 数据结构和算法(Golang实现)(22)排序算法-希尔排序

    希尔排序 1959 年一个叫Donald L. Shell (March 1, 1924 – November 2, 2015)的美国人在Communications of the ACM 国际计算机 ...

  6. 【翻译】Java Array的排名前十方法(Top 10 Methods for Java Arrays)

    这里列举了Java Array 的前十的方法.他们在stackoverflow最大投票的问题. The following are top 10 methods for Java Array. The ...

  7. 【Java】关键字 和 保留字

    Java的关键字[Keyword]和 保留字[Reserved word] 官方描述: https://docs.oracle.com/javase/tutorial/java/nutsandbolt ...

  8. Java读源码之CountDownLatch

    前言 相信大家都挺熟悉 CountDownLatch 的,顾名思义就是一个栅栏,其主要作用是多线程环境下,让多个线程在栅栏门口等待,所有线程到齐后,栅栏打开程序继续执行. 案例 用一个最简单的案例引出 ...

  9. spring boot连接linux服务器上的redis

    本文章为给新手学习spring boot远程连通redis提供一个学习参考. 环境是intellij idea(window)+ redis(linux虚拟机-vmware). 首先在linux安装好 ...

  10. bootstrop日历

    https://blog.csdn.net/cuixiaobo521/article/details/77880633