【muduo】线程池
来源:互联网 发布:看书哪个软件好 编辑:程序博客网 时间:2024/05/21 10:39
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& 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_; // 线程列表 ptr_vector是boost库的指针容器 boost::ptr_vector<muduo::Thread> threads_; // 任务队列 std::deque<Task> queue_; // 任务队列的最大数值 size_t maxQueueSize_; // 线程池是否正在运行 bool running_;};}#endif
ThreadPool.cpp
// 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); //创建线程并启动 threads_.push_back(new muduo::Thread( boost::bind(&ThreadPool::runInThread, this), name_+id)); threads_[i].start(); } // 如果要求创建线程的数目为0,并且设定了线程池初始化回调函数,就调用线程池初始化回调函数 if (numThreads == 0 && threadInitCallback_) { threadInitCallback_(); }}// 停止线程池void ThreadPool::stop(){ { MutexLockGuard lock(mutex_); running_ = false; notEmpty_.notifyAll(); } // 阻塞并等待所有线程执行完毕 for_each(threads_.begin(), threads_.end(), boost::bind(&muduo::Thread::join, _1));}// 获取线程池任务队列数目size_t ThreadPool::queueSize() const{ MutexLockGuard lock(mutex_); return queue_.size();}// 处理任务void ThreadPool::run(const Task& task){ if (threads_.empty()) { //如果线程池中没有处理线程,就直接执行任务,注意并没有重新开始一个新的线程,所以是以阻塞方式进行 task(); } else { // 否则,就等待任务队列不满的情况下,将任务加入任务队列,并通知线程任务队列已经非空 MutexLockGuard lock(mutex_); while (isFull()) { notFull_.wait(); } assert(!isFull()); queue_.push_back(task); notEmpty_.notify(); }}// C++11 的右值引用版本#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// 从任务对垒中取出一个任务ThreadPool::Task ThreadPool::take(){ MutexLockGuard lock(mutex_); // always use a while-loop, due to spurious wakeup // 等待任务队列非空 while (queue_.empty() && running_) { notEmpty_.wait(); } // 取出任务队列 Task task; if (!queue_.empty()) { task = queue_.front(); queue_.pop_front(); // 通知其他线程,任务队列不满 if (maxQueueSize_ > 0) { notFull_.notify(); } } return task;}// 判断任务队列是否已满bool ThreadPool::isFull() const{ mutex_.assertLocked(); return maxQueueSize_ > 0 && queue_.size() >= maxQueueSize_;}// 这个就是线程处理函数,主要功能就是开始一个循环,然后从任务队列中取出任务,并执行任务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:线程池
- 【muduo】线程池
- muduo源码分析:线程池类ThreadPool
- muduo源码分析--线程池的实现
- muduo 之线程(13)
- muduo库阅读(9)——线程池
- muduo网络库学习笔记(5):线程池的实现
- muduo库中对线程池的实现(1)
- muduo库中对线程池的实现(2)
- [Muduo网络库源码分析] (10) base/ThreadPoll_cc_h_线程池
- Muduo库源码分析(7):线程池
- linux-muduo线程通信eventfd
- 利用muduo原线程池修改的可调度线程池源码
- muduo网络库:线程之间的同步机制(使用eventfd函数,条件变量,线程池)
- muduo网络库源码学习————线程池实现
- muduo库阅读(36)——Net部分:事件循环线程池EventLoopThreadPool
- muduo网络库学习(八)事件驱动循环线程池EventLoopThreadPool
- Muduo里的blockingQueue实现线程池伪码
- B
- Hadoop的WordCount案例
- 《图解 HTTP》读书笔记(三)
- c++类和对象,构造函数,函数重载,复合类。
- Java 生产者消费者
- 【muduo】线程池
- 关于workerman在Thinkphp5的应用
- 仿京东下拉刷新动画的源码查看——自定义控件学习(一)
- 安卓长安保存图片三种方案的对比
- Solr-6.5.1之Solrj的使用
- poj-1836-士兵出列问题-双向LIS
- Linux下PHP安装curl扩展支持https
- 【并查集】poj 1611 The Suspects
- 堆排序