ThreadPool提供Reactor/Proactor服务,并且强偶合了Reactor(反应器)/Proactor(前摄器)。不同于Reactor/Proactor使用线程池
进行事件处理的设计。如ACE框架的ACE_TP_Reactor。
同时ThreadPool提供一个共享的工作分派队列,可以用作Half-Async/Half-sync并发模式的线程池。
ThreadPool为池中每个线程定制了一至的线程循环,运行在池中的线程者必须进行这个循环,接受线程池的统一控制。
此外ThreadPool还强偶合了每一个事件处理类,线池程的相关控制也偶合进事件处理程序中去。

ThreadPool组件包含下面的协作类:
ThreadPoolCurrent,是ThreadPool和EventHandlerThread的一个关联
EventHandlerThread,运行在ThreadPool的线程。
Selector,反应器(当不使用IOCP),或前摄器(当使用IOCP)。
ThreadPoolWorkQueue,工作分派队列,优先级别比网络IO事件低。使用ThreadPool进行dispatch的任务都入队到ThreadPoolWorkQueue


EventHandler,定义了可以在线程池执行的事件处理程序的抽象接口。
ThreadPool组件只处理(或者说提供现成的)三种具体的事件:
ThreadPoolWorkQueue,工作队列消费事件。
ConnectionI,网络连接上读写事件,它的事件处理程序强偶合了Ice协议。
IncomingConnectionFactory,被动网络连接事件。
这里要指出ThreadPool还强偶合了上面每一个事件处理类,线池程的相关控制也偶合进事件处理程序"EventHandler::message"中去。

下面还会进一步说明。

相信这时你一定很想听到ThreadPool使用了高性能的Leader/Followers并发模式了。但是要清楚不是使用了LF模式就代表你的软件就高

性能了,LF模式虽然说高性能但也不是什么情况都使用,LF模式是设计用来解决某些模式在某些特定情况的问题的。在Ice的

ThreadPool组件设计中,在使用IOCP前摄器的版本就没有使用LF模式。为什么?因为LF模式不是最佳的选择,在使用IOCP的前摄器没有

LF模式针对解决的问题发生,反而帮倒忙。
ThreadPool组件在使用Reactor(反应器)的版本使用Leader/Followers并发模式,而在Proactor(前摄器)的版本不使用

Leader/Followers并发模式。

ThreadPool组件使用单方法分派接口策略,同一句柄的所有事件类型的事件处理集中在一个单独的事件处理方法。而ACE的设计则是使

用多方法分派接口策略,同一句柄不同事件类型的事件处理分别对应特定的事件处理钩子方法。ThreadPool组件使用单方法分派接口策

略,将具体的事件类型分派交给事件处理方法内进行,而不是由Reactor(反应器)或Proactor(前摄器)最终决定。

EventHandler是一个抽象类,虽然定义了事件处理抽象方法message,却同时也定义事件状态。
事件类型包含Read,Write等,由SocketOperation枚举类型来定义。
EventHandler定义许多由SocketOperation组成的状态。
用于控制的状态:_registered,_ready,_disable。
_registered:一个具体的事件处理类关联到ThreadPool(反应器或前摄器强偶合在ThreadPool)。
_ready:从反应器或前摄器接收事件的逻辑之外,对事件进行激活。
_disable:使用反应器版本的ThreadPool的动态控制。
用于前摄器异步操作状态:_pending,_started,_completed。
_pending:
_started:发起了一次异步I/O操作
_completed:发起了的一次异步I/O操作完成了
此外,EventHandler不保存由反应器或前摄器接收到事件的接收状态,而是在ThreadPool的map容器中,由线程池线程共享。

ThreadPool将事件处理程序分为两阶段,第一阶段是IO,第二阶段是User。在使用Reactor(反应器)版本中,网络指示事件通知了句

柄不再阻塞,可以放心进行同步I/O操作,所以事件处理程序首先要对指示事件进行响应进行同步I/O操作,然后才是事件用于I/O以外

的操作,也就是真正的dispatch。在使用Proactor(前摄器)版本中,事件处理程序并不包含第一阶段,因为异步I/O操作由系统进行

了,并且事件是异步I/O操作的完成事件。ThreadPool统计这两个阶段的事件处理状态的线程数量,用来对线程池整体的控制。
ThreadPool使用_inUseIO对事件处理进行IO阶段的线程统计,_inUse对事件处理进行dipatch阶段的线程统计。
_inUseIO统计数决定是否要进行Leader的推选(promote),只有在反应器版本有效。每次线程以leader身份取出一个事件处理对象,

对相关事件进行同步I/O之前,都要参加统计计数即加1。在完成同步I/O之后,释放统计计数即减1,并根据统计是否要推选。因为反应

器不希望有句柄进行同步I/O的同时而进行阻塞等待句柄的事件。当还有已得事件未处理时,则不用理会这个统计计数而进行推选唤醒

线程处理已得事件。
_inUse统计数决定是否要新增线程,如果正在dispatch的线程数量已经到达了当前ThreadPool拥有的线程数目,还未到达最大限制数目

的时候,必须新增线程。
因为ThreadPool组件在使用LF模式的版本中,引入了_inUseIO统计数来控制竞选的进程(progress,是否允许新一轮的竞选)。并且这

个_inUseIO统计数的功能强偶合进了事件处理类(EventHandler的继承类)的事件处理程序(EventHandler::message)中,事件处理

程序必须对_inUseIO统计数进行释放,如果这个_inUseIO统计数发生了意外,你的LF竞选可能就永远不会进行新一轮的选举,以至候选

线程不可能被唤醒。如果你不明白这一点,去添加自己的事件处理类的话,就可能因没有在事件处理程序中释放这个_inUseIO统计数而

惹上麻烦。虽然Ice在ThreadPool的线程循环里,在事件处理程序执行之后小心地照料了这个_inUseIO统计数,但还是有可能事件处理

程序异常等其它原因,使得你没的程序运行没有按照Ice设计的流程进行,只要有一次_inUseIO统计数没有被正确释放,你的线程池就

会惹上麻烦。
此外,ThreadPool引入的另一个用于线程池控制的统计数_inUse,同样也强偶合在事件处理程序。并且由这个_inUse统计数感知压力而

新增线程的工作也是偶合在事件处理程序。当这个统计数发生错乱后,你可以失去以下便利。尽管你的线程池线程数目没有达到上限,

当前可用线程都用尽了,但也不能新添加线程。而你池中有线程因为异常面退出了,线程池规模缩小,却不能新添加线程补充。

由于ThreadPool引入了上面一些统计数来控制线程池,因此线程池的线程对象EventHandlerThread有下面几种状态:Idle,ForIO,

ForUser等。当线程在上面的状态切换时,都要通知相关的observer。ThreadPool的线程执行的整个流程中,还有许多的事件监视点,

即有许多各类的Observer,这将分开一篇独立写。

ThreadPool提供默认dispatch策略,以及支持自定义dispatcher策略。默认dispatch策略,事件处理执行在当前线程。自定义

dispatcher策略则由用户自定义,并在Ice环境Communicator创建时指定。

ZeroC ICE的远程调用框架 ThreadPool的更多相关文章

  1. ZeroC ICE的远程调用框架 Slice如何帮助我们进行Ice异步编程(AMI,AMD)

    Slice最大的用处就是为我们使用Ice进行编程,代劳绝大部分的重复性代码,并提供一些帮助性的框架代码,如用于AMI和AMD方式进行异步编程的回调框架. 当Slice不为我们生成代码时,我们仍然可以按 ...

  2. ZeroC ICE的远程调用框架 AMD

    继上一篇<ZeroC ICE的远程调用框架>,本篇再来说其中的AMD.(本篇需要重写) 当在ice文件中声明某个接口方法Method为["amd"]后,接口方法在stu ...

  3. ZeroC ICE的远程调用框架

    想搞清楚slice为我们生成了什么样的框架代码,就先搞明白Ice的远程调用框架暗中为我们做了些什么? Ice将Ice Object的方法调用分为三个阶段(或步骤),分别是begin,process和e ...

  4. ZeroC ICE的远程调用框架 AMI与AMD -Why?

    在Ice有两种异步使用的方式,AMI和AMD.AMI是异步方法调用,AMD是异步方法调度(分派).前者用在代理端,后者用在饲服实现端. AMI其实就是在代理端,使用Future机制进行异步调用,而不阻 ...

  5. ZeroC ICE的远程调用框架 Callback(一)-AMI异步方法调用框架

    Ice框架提供了不少回调设施,其中一些是使用Ice远程调用进行ami模式或amd模式的支撑.本篇来看一下用于代理端的回调设施. Ice代码中有好几个Callback相关命名的基类,并且slice还会为 ...

  6. ZeroC ICE的远程调用框架 class与interface

    我们在ice文件中定义的class或interface,slice都会为我们生成stub存根类和skeleton骨架类.在这里要注意slice并没有分别生成两份单独用在客户端或服务端的接口给开发分发. ...

  7. ZeroC ICE的远程调用框架 ServantLocator与Locator

    ServantLocator定位的目标是Servant,而Locator定位的目标是“Ice Object”,即一个可定位的“Ice Object”代理.Servant是::Ice::Object的继 ...

  8. ZeroC ICE的远程调用框架 代理引用地址

    在官方文档中称为Binding,协议-地址对的绑定.在Proxy模式中,一般地有三个参与者,Proxy,Subject以及RealSubject.Subject定义了Proxy(代理)和RealSub ...

  9. ZeroC ICE的远程调用框架 ASM与defaultServant,ServantLocator

    ASM与defaultServant,ServantLocator都是与调用调度(Dispatch)相关的. ASM是ServantManager中的一张二维表_servantMapMap,默认Ser ...

随机推荐

  1. MySQL GROUP_CONCAT()函数 -- 字段合并查询

    在做查询的时候遇到一个问题,今天分享一下解决方法. 先看一下我想要什么效果. 清单名称类型要点,后面两列为清单步骤(外键表) 但我并不想让主表的内容重复那么多遍,于是 distinct去重.子查询.左 ...

  2. 玩转OneNET物联网平台之MQTT服务⑦ —— 远程控制LED(数量无限制)+ Android App控制 优化第一版

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  3. Spring Cloud - Eureka /actuator/info 如何显示信息

    在pom.xml中添加 <!-- actuator监控信息完善 --> <dependency> <groupId>org.springframework.boot ...

  4. Java IO编程——字符流与字节流

    在java.io包里面File类是唯一 一个与文件本身有关的程序处理类,但是File只能够操作文件本身而不能够操作文件的内容,或者说在实际的开发之中IO操作的核心意义在于:输入与输出操作.而对于程序而 ...

  5. spring-boot-plus V1.4.0发布 集成用户角色权限部门管理

    RBAC用户角色权限 用户角色权限部门管理核心接口介绍 Shiro权限配置

  6. Mybatis JdbcType与Oracle、MySql 数据类型对应关系

    MyBatis 包含的jdbcType类型 ------------------------------------------------------------------------------ ...

  7. Android 设备唯一标识(多种实现方案)

    前言 项目开发中,多少会遇到这种需求:获得设备唯一标识DeviceId,用于: 1.标识一个唯一的设备,做数据精准下发或者数据统计分析: 2.账号与设备绑定: 3..... 分析 这类文章,网上有许多 ...

  8. vue学习之深入响应式原理

    vue的响应式原理 当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全 ...

  9. [考试反思]1106csp-s模拟测试103: 渺茫

    7点之前上不了博客,用gedit写的.谅解一下. 看起来不是特别惨?但是被sdfz爆踩了...而且其实并不能说“不是特别惨”吧90分算个啥啊?还凑不出个T2的AC难易度评估错误,T2是最简单的没看出来 ...

  10. [LLL邀请赛]参观路线(图论+dfs)

    emmmm....学校的oj被查水表了,扒不到原题面,所以.... 但是我还是扒到了题面... 题目大意:给定一个完全图,删掉其中一些边,然后求其字典序最小的遍历顺序 有点像去年day2T1啊.... ...