POCO C++库学习和分析 --  线程 (二)


3.  线程池

3.1线程池的基本概念

首先我们来明确线程池的一些概念。

       什么是线程池?线程池的好处?

池的英文名:POOL,可以被理解成一个容器。线程池就是放置线程对象的容器。我们知道线程的频繁创建、销毁,是需要耗费一点的系统资源的,如果能够预先创建一系列空线程,在需要使用线程时侯,从线程池里,直接获取IDLE线程,则省去了线程创建的过程,当有频繁的线程出现的时候对性能有比较大的好处,程序执行起来将非常效率。

       什么时候推荐使用线程池?

很明显,线程越频繁的被创建和释放,越是能体现出线程池的作用。这时候当然推荐使用线程池。

       什么时候不推荐使用线程池?

推荐线程池使用的反面情况喽。

比如长时间运行的线程(线程运行的时间越长,其创建和销毁的开销在其生命周期中比重越低)。

需要永久标识来标识和控制线程,比如想使用专用线程来终止该线程,将其挂起或按名称发现它。因为线程池中的线程都是平等的。

       线程池需要具备的元素

  • 线程池要有列表,可以用来管理多个线程对象。
  • 线程池中的线程,具体执行的内容,可自定义。
  • 线程池中的线程,使用完毕后,还能被收回,供下次使用。
  • 线程池要提供获取空闲(IDLE)线程方法。当然这个方法可以被封装在线程池中,成为其内部接口。

3.2 Poco中线程池实现

先看一看Poco中内存池的类图吧。

对于Poco中的线程池来说,设计上分成了两层。第一层为ThreadPool,第二层为PooledThread对象。

第一层中,ThreadPool负责管理线程池,定义如下:

class ThreadPool
{
public:ThreadPool(int minCapacity = 2,int maxCapacity = 16,int idleTime = 60,int stackSize = POCO_THREAD_STACK_SIZE);ThreadPool(const std::string& name,int minCapacity = 2,int maxCapacity = 16,int idleTime = 60,int stackSize = POCO_THREAD_STACK_SIZE);~ThreadPool();void addCapacity(int n);int capacity() const;void setStackSize(int stackSize);int getStackSize() const;int used() const;int allocated() const;int available() const;void start(Runnable& target);void start(Runnable& target, const std::string& name);void startWithPriority(Thread::Priority priority, Runnable& target);void startWithPriority(Thread::Priority priority, Runnable& target, const std::string& name);void stopAll();void joinAll();void collect();const std::string& name() const;static ThreadPool& defaultPool();protected:PooledThread* getThread();PooledThread* createThread();void housekeep();private:ThreadPool(const ThreadPool& pool);ThreadPool& operator = (const ThreadPool& pool);typedef std::vector<PooledThread*> ThreadVec;std::string _name;int _minCapacity;int _maxCapacity;int _idleTime;int _serial;int _age;int _stackSize;ThreadVec _threads;mutable FastMutex _mutex;
};

从ThreadPool的定义看,它是一个PooledThread对象的容器。职责分成两部分:

第一,维护和管理池属性,如增加线程池线程数目,返回空闲线程数目,结束所有线程

第二,把需要运行的业务委托给PooledThread对象,通过接口start(Runnable& target)

void ThreadPool::start(Runnable& target)
{getThread()->start(Thread::PRIO_NORMAL, target);
}

函数getThread()为ThreadPool的私有函数,作用是获取一个空闲的PooledThread线程对象,实现如下

PooledThread* ThreadPool::getThread()
{FastMutex::ScopedLock lock(_mutex);if (++_age == 32)housekeep();PooledThread* pThread = 0;for (ThreadVec::iterator it = _threads.begin(); !pThread && it != _threads.end(); ++it){if ((*it)->idle()) pThread = *it;}if (!pThread){if (_threads.size() < _maxCapacity){pThread = createThread();try{pThread->start();_threads.push_back(pThread);}catch (...){delete pThread;throw;}}else throw NoThreadAvailableException();}pThread->activate();return pThread;
}

第二层中PooledThread对象为一个在线程池中线程。作为线程池中的线程,其创建于线程池的创建时,销毁于线程池的销毁,生命周期同线程池。在其存活的周期中,状态可分为running task和idle。running状态为正在运行业务任务,idle为线程为闲置状态。Poco中PooledThread继承自Runnable,并且包含一个Thread对象。

class PooledThread: public Runnable
{
public:PooledThread(const std::string& name, int stackSize = POCO_THREAD_STACK_SIZE);~PooledThread();void start();void start(Thread::Priority priority, Runnable& target);void start(Thread::Priority priority, Runnable& target, const std::string& name);bool idle();int idleTime();void join();void activate();void release();void run();private:volatile bool        _idle;volatile std::time_t _idleTime;Runnable*            _pTarget;std::string          _name;Thread               _thread;Event                _targetReady;Event                _targetCompleted;Event                _started;FastMutex            _mutex;
};

对于PooledThread来说,其线程业务就是不断的检测是否有新的外界业务_pTarget,如果有就运行,没有的话,把自己状态标志位限制,供线程池回收。

void PooledThread::run()
{_started.set();for (;;){_targetReady.wait();_mutex.lock();if (_pTarget) // a NULL target means kill yourself{_mutex.unlock();try{_pTarget->run();}catch (Exception& exc){ErrorHandler::handle(exc);}catch (std::exception& exc){ErrorHandler::handle(exc);}catch (...){ErrorHandler::handle();}FastMutex::ScopedLock lock(_mutex);_pTarget  = 0;
#if defined(_WIN32_WCE)_idleTime = wceex_time(NULL);
#else_idleTime = time(NULL);
#endif  _idle     = true;_targetCompleted.set();ThreadLocalStorage::clear();_thread.setName(_name);_thread.setPriority(Thread::PRIO_NORMAL);}else{_mutex.unlock();break;}}
}

Poco中线程池的实现,耦合性其实是很低的,这不得不归功于其在线程池上两个层次的封装和抽象,类的内聚性非常强的,每个类各干各的事。

3.3 其他

除了上面线程池的主要属性和接口外,Poco中线程池还实现了一些其他特性。如设置线程运行的优先级,实现了一个默认线程的单件等。

(版权所有,转载时请注明作者和出处 http://blog.csdn.net/arau_sh/article/details/8592579)

转载于:https://www.cnblogs.com/napu/archive/2013/02/19/5375911.html

POCO C++库学习和分析 -- 线程 (二)相关推荐

  1. POCO C++库学习和分析

    POCO C++库学习和分析 -- 序 1. POCO库概述: POCO是一个C++的开源库集.同一般的C++库相比,POCO的特点是提供了整一个应用框架.如果要做C++程序应用框架的快速开发,我觉得 ...

  2. POCO C++库学习和分析 -- 序

    POCO C++库学习和分析 -- 序 1. POCO库概述: POCO是一个C++的开源库集.同一般的C++库相比,POCO的特点是提供了整一个应用框架.如果要做C++程序应用框架的快速开发,我觉得 ...

  3. POCO C++库学习和分析 -- 异常、错误处理、调试

    POCO C++库学习和分析 -- 异常.错误处理.调试 1. 异常处理 C++同C语言相比,提供了异常机制.通过使用try,catch关键字可以捕获异常,这种机制使得程序员在程序异常发生时,可以通过 ...

  4. POCO C++库学习和分析 -- 字符编码

    POCO C++库学习和分析 -- 字符编码 1. 字符编码 1.1 字符编码的概念 字符编码可以理解为在计算机上语言符号和二比特数之间的映射.不同的编码方式对应着不同映射方法,对于映射集的双方而言, ...

  5. poco,c++库学习,日期和时间

     POCO C++库学习和分析 -- 日期与时间 在Poco库中,与时间和日期相关的一些类,其内部实现是非常简单的.看相关文档时,比较有意思的倒是历史上的不同时间表示法. 1. 系统时间函数    ...

  6. 26muduo_net库源码分析(二)

    1.类图 2.Channel (1)Channel是selectable IO channel,负责注册与响应IO事件,它不拥有filedescriptor. (2)Channel是Acceptor. ...

  7. Golang 库学习笔记 Gin(二)

    介绍 Gin 是一个用 Go (Golang) 编写的 web 框架. 它是一个类似于 martini 但拥有更好性能的 API 框架, 由于 http router,速度提高了近 40 倍. 如果你 ...

  8. 11muduo_base库源码分析(二)

    1.为什么需要原子性操作 (1)x++; (2)从内存中读x的值到寄存器中,对寄存器加1,再把新值写回x所处的内存地址 2.gcc原子性操作 (1)原子自增操作 type __sync_fetch_a ...

  9. C++STL标准库学习总结/索引/学习建议

    前言: 如果刚刚开始学习STL标准库,不知道从哪里入手学习的话,建议去中国大学mooc平台,先学习北京大学郭炜老师的<程序设计与算法(一)C语言程序设计>(https://www.icou ...

  10. Guava库学习:学习Guava EventBus(二)EventBus 事件订阅示例

    2019独角兽企业重金招聘Python工程师标准>>> 原文地址:Guava库学习:学习Guava EventBus(二)EventBus 事件订阅示例 上一篇Guava库学习:学习 ...

最新文章

  1. 部署可扩展的目标检测管道:推理过程(上)
  2. 10个必会的 PyCharm 技巧
  3. Spark(四) -- Spark工作机制
  4. 百万数据报表导出:原理分析与总结
  5. php+node+redis,redis,nodejs,php,pub/sub 实战: 微信语音识别
  6. springboot-vue项目前台1
  7. this到底指向哪里
  8. Linux的sort命令
  9. junit进行单元测试_通过JUnit规则轻松进行AppEngine单元测试
  10. 如何手动修改XP系统属性中的技术支持信息
  11. matlab考试题烟台大学,徐骞-计算机控制与工程学院
  12. [Ext JS ][12.13] FieldSet 与 Grid结合 ,实现FieldSet 显示Gird中Store 的数量
  13. 猜51CTO的人群结构
  14. t-SNE可视化-Python实现
  15. 【论文笔记】BusTr,基于实时交通数据的公交旅行时间预测
  16. 电机噪音测试:手持式噪音计术语1
  17. 【MySQL 8.0 OCP 1Z0-908认证考试】 题库精讲--第二讲mysql主从
  18. Pytorch+PyG实现GraphConv
  19. 有两台计算机的IP地址分别为:192.168.1.100 和 192.168.2.10请问该采取什么样的办法让他们通信?
  20. Android项目小记——nomedia文件与MediaStore媒体库

热门文章

  1. 史上最全的Maven Pom文件标签详解
  2. ElasticSearch常用API操作示例
  3. 09. 斐波那契数列(C++版本)
  4. JAVAWeb项目 微型商城项目-------(一)项目描述
  5. gatewayworker配置php,tp5整合GatewayWorker
  6. 服务器win10系统开机慢,Win10系统开机慢怎么办 windows10开机慢的解决方法
  7. MySQL:设置字段默认为当前时间
  8. Java编程:多路查找树
  9. jQuery特效:实现瀑布流
  10. java 符_java运算符