先讨论pool之概貌
说到池,对于java来说,我们最熟悉的莫过于线程池了。而Apache common pool虽经常使用(jedis连接池,数据库连接池),但却真是“日用而不知”。但其道理乃是共同的,毕竟法门不二。
线程池,我们常说它是资源管理,以符合我们使用场景所需要的参数定义。 所以我们不妨先看看线程池
线程池
1. 常用参数
| 参数 | 意义 |
|---|---|
| corePoolSize | 核心线程数 |
| maximumPoolSize | 最大线程数 |
| workQueue | 工作队列,可是做数据的暂时缓存之所 |
| keepAliveTime | 存活时间 |
| allowCoreThreadTimeOut | 是否允许核心线程超时 |
| RejectedExecutionHandler | 拒绝策略 |
这些参数大抵可以分为三种
- 资源上下限数据--corePoolSize maximumPoolSize
- 资源的生命周期--keepAliveTime
- 资源在使用时,当遵循如何的规定--workQueue allowCoreThreadTimeOut RejectedExecutionHandler
有以上的三种类型的参数,池的骨架,已经具备,而剩余之事乃是为其赋予筋肉。
2. 核心逻辑
- 池之状态
- 创建池中对象
- 销毁池中对象
- 安排池中对象,当如何进行工作
- 反馈机制,即根据池的状态,池中对象的生命周期,来及时进行处理,以维持池之稳定
- 反馈机制,则必然先要有数据之支撑(相关数据之统计,相关状态之转变)
- 然后再是,对其数据做出预定的逻辑处理
以上五者,同人之五官,若其有缺,则世途难行,非习得他种本领不可,以作人生之挽救。
general pool vs 线程池
线程池之结构,虽能为我们所鉴,然其亦有缺憾也。 究其固结,乃是其本身独立,而与外之服务无扰,譬如数据库,redis之类数据安放server。 而这正是general pool所要考量之处,故需更多参数加以辅佐完备逻辑值实现。
general pool
首先我们的创建有效的池中对象,因为检查对象,当视为首要之一。
池中对象的检查
- 检查池中对象与外界服务器正常连通。这种检查的时机比较重要,这种时机,涉及到了两种检查风格。
| 检查方式 | 效果与影响 |
|---|---|
| 每次创建/使用时,进行检查 | 可以确保每次都能获取有效的对象,实时性好,但可能给外服务带来多余的意义不大的请求,从而降低整个性能 |
| 周期性检查 | 不会给外服务器多余的请求,不能确保每次都能获取有效的对象,实时性差 |
- 不能正常连通时,是否需要重试。
- 需要重试时,重试次数,时间上的限制,也就自然而来
再者回归到资源有限上来考量。
池中的对象,就其活跃程度来衡量,可分为两类,繁忙与空闲。
繁忙者,自然不可抛弃。空闲者,则需权衡以处之。
空闲对象的处置参数
- 空闲对象的数量限制(可以有上下界限)
- 空闲对象的空闲时间限制
- 空闲对象当如何清除掉(这涉及到池中的清除机制)
清除机制
- 前提条件,池中需要有统计数据,来区分各种状态的对象,以及对应的数量。
- 清除机制一般是一个定时任务,进行定期的扫描,判断,处理,维护池的稳定。
- 定时任务的周期时间
- 扫描池中对象的方式(比如,全部都扫描,还是只扫描一部分,池中对象的遍历方式(顺序还是倒序))
- 判断池中对象是否可以清除
- 如不可清除,是否需要检查当前对象的有效性,是否需要激活它,再次使用
- 清除完毕后,是否有违背池的定义(比如池中对象的数目是否还满足最小值,池中空闲数量是否还满足最小值)
至此general pool之全貌,虽未尽睹,但正如画龙之法,龙之鳞爪已露,至于身躯,本当深藏云中,乃为善也。