[Muduo网络库源码分析] (10) base/ThreadPoll_cc_h_线程池
来源:互联网 发布:酒店市场数据分析 编辑:程序博客网 时间:2024/06/05 10:52
线程池
实现:ThreadPool类
功能:实现固定大小的线程池,用来高效的处理大量任务
知识点:
- 回调函数
通俗的讲,回调函数就是在放在另一个函数中执行的函数,在回调中,我们利用某种方式,把回调函数像参数一样传入中间函数。 - boost::ptr_vector
Boost中的指针容器
threads_.reserve 设置指针容器的大小 - for_each
for_each 算法范围 [first, last) 中的每个元素调用函数 F,并返回输入的参数 f。此函数不会修改序列中的任何元素。
用途:
可用于创建线程,创建多线程程序,可用于创建线程池。
模块拆分与封装:
已把其线程池对象模块单独分离出来,并利用Makefile统一编译,模块代码地址如下:https://github.com/chudongfang/Learn_From_Muduo/tree/master/ThreadPoll
代码及分析:
ThreadPoll.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& nameArg = string("ThreadPool")); ~ThreadPool(); // Must be called before start(). //设置线程池最大线程数量 void setMaxQueueSize(int maxSize) { maxQueueSize_ = maxSize; } //设置线程初始化回调函数 void setThreadInitCallback(const Task& cb) { threadInitCallback_ = cb; } //开启线程池 void start(int numThreads); //停止线程池 void stop(); //返回线程池名 const string& name() const { return name_; } //返回队列大小 size_t queueSize() const; // Could block if maxQueueSize > 0 //向任务队列放入任务 void run(const Task& f);#ifdef __GXX_EXPERIMENTAL_CXX0X__ void run(Task&& f);#endif private: bool isFull() const;//判断线程池是否满 void runInThread(); //子进程函数,在子进程中执行任务 Task take(); //从任务队列中取任务 mutable MutexLock mutex_;//互斥锁,保证数据互斥访问 Condition notEmpty_; //条件变量,是否为空 Condition notFull_; //条件变量,是否满 string name_; //线程名字 Task threadInitCallback_;//线程初始化化回调函数 boost::ptr_vector<muduo::Thread> threads_;//线程队列,利用指针容器实现 std::deque<Task> queue_; //双向队列 size_t maxQueueSize_; //最大队列容量 bool running_; //线程池是否运行};}#endif
ThreadPoll.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& nameArg) : mutex_(),//初始化锁 notEmpty_(mutex_),//初始化条件变量 notFull_(mutex_), name_(nameArg), //初始化线程池名 maxQueueSize_(0), 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+1); //新建立进程,并用bind绑定函数进行传参 threads_.push_back(new muduo::Thread( boost::bind(&ThreadPool::runInThread, this), name_+id)); //运行线程 threads_[i].start(); } //初始化回调函数 if (numThreads == 0 && threadInitCallback_) { threadInitCallback_(); }}void ThreadPool::stop(){ { //加互斥锁,当其出当前{}后会自动析构,并解锁 MutexLockGuard lock(mutex_); running_ = false; //以广播的形式唤醒等待notEmpty条件变量的线程 notEmpty_.notifyAll(); } //遍历这个容器,并在每个线程中执行join函数,对线程进程阻塞 for_each(threads_.begin(), threads_.end(), boost::bind(&muduo::Thread::join, _1));}//返回队列长度size_t ThreadPool::queueSize() const{ //MutexLockGuard类对mutex_加锁,当函数结束时,其会自动利用析构函数解锁 MutexLockGuard lock(mutex_); return queue_.size();}//主线程函数//不断添加task到task队列void ThreadPool::run(const Task& task){ //如果线程池中没有线程,由主线程执行task if (threads_.empty()) { task(); } else { MutexLockGuard lock(mutex_); //如果线程池满,则阻塞等待子线程对task进行处理 while (isFull()) { notFull_.wait(); } assert(!isFull()); //向线程队列中添加task queue_.push_back(task); //唤醒子线程处理task notEmpty_.notify(); }}#ifdef __GXX_EXPERIMENTAL_CXX0X__void ThreadPool::run(Task&& task){ if (threads_.empty()) { task(); } else { MutexLockGuard lock(mutex_); while (isFull()) { notFull_.wait(); } assert(!isFull()); queue_.push_back(std::move(task)); notEmpty_.notify(); }}#endif//子线程函数//从任务队列(queue)中取taskThreadPool::Task ThreadPool::take(){ MutexLockGuard lock(mutex_); // always use a while-loop, due to spurious wakeup //子进程等待任务队列中的task while (queue_.empty() && running_) { notEmpty_.wait(); } Task task; //从任务队列中取task if (!queue_.empty()) { task = queue_.front(); queue_.pop_front(); //唤醒其他子线程来取task,保证了task被挨个取走 if (maxQueueSize_ > 0) { notFull_.notify(); } } return task;}//判断队列是否满bool ThreadPool::isFull() const{ mutex_.assertLocked(); return maxQueueSize_ > 0 && queue_.size() >= maxQueueSize_;}//子线程函数//利用回调函数初始化线程//从任务队列中取task并执行//抛出异常void ThreadPool::runInThread(){ try { if (threadInitCallback_) { threadInitCallback_(); } 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 }}
阅读全文
0 0
- [Muduo网络库源码分析] (10) base/ThreadPoll_cc_h_线程池
- [Muduo网络库源码分析] (9) base/Thread.cc_h_CurrentThread_h线程对象
- [Muduo网络库源码分析] (1) base/Atomic.h_原子操作与原子整数
- [Muduo网络库源码分析] (2) base/Condition.cc_h_条件变量操作
- [Muduo网络库源码分析] (3) base/CountDownLatch.cc_h_“倒计时门闩”同步
- [Muduo网络库源码分析] (4) base/Exception_cc_h_带 stack trace 的异常基类
- [Muduo网络库源码分析] (5) base/FileUtil.cc_h_文件操作
- [Muduo网络库源码分析] (6) base/Mutex.h_互斥锁操作
- [Muduo网络库源码分析] (7) base/Singleton.h_SINGLETON对象创建型模式
- [Muduo网络库源码分析] (8) base/StringPiece.h_字符串参数传递类型
- [Muduo网络库源码分析] (11) base/Types.h_基本类型声明
- Muduo库源码分析(7):线程池
- muduo源码分析:线程池类ThreadPool
- muduo源码分析--线程池的实现
- muduo网络库源码分析-定时器
- muduo库源码分析
- muduo库源码学习(base)Atomic
- muduo库源码学习(base)AsyncLogging
- kubernetes1.8发布跟踪
- 完美解决MyEclipse提示过期Your 30-day trial of MyEclipse has expired.
- spring+oauth 遇到的问题
- ios中列表UITableView的使用
- 【LeetCode】valid-parenthesis
- [Muduo网络库源码分析] (10) base/ThreadPoll_cc_h_线程池
- linux常用文件操作命令
- 智能版石头剪刀布——c++实现
- Webpack "Invalid Host Header"
- UITableView+FDTemplateLayoutCell xib demo 例子
- MVC5学习小记(4):自定义授权过滤器
- PMM部署遇到的坑
- 学习规划
- s2sh 分发服务