资源的分配与回收——池

简介

我们都有听过单例模式,即通过控制对象的创建(构造函数私有化)将对象的个数限制为1个。实际场景下,单例的场景毕竟是有限的。

在java程序中,要提高应用的性能,有以下两类情形

  1. 大量、频繁创建和回收的对象。如果这些对象的生命周期都很短暂,会导致频繁YoungGC;如果生命周期很长,会导致大量Full GC。gc过程会影响java程序的性能。
  2. 一些创建起来较为耗时的对象,比如线程和连接

所以最好的办法是,我们一开始创建一定数量的对象,然后复用这些对象。

资源限制也是一种保护策略,比如数据库链接池。除去这些对象本身的开销外,他们对外部系统也会造成压力,比如大量创建连接对DB也是有压力的。池化除了优化资源以外,本身限制了资源数,对外部系统也起到了一层保护作用。

对象池

内存是byte[]级的复用,对象池是对象级的内存复用。对象池就相当于内存管理器,只不过内存分配和回收的级别是对象。

享元模式,另一种池技术

在对象池中,对象的实例个数往往是由程序人员根据应用负载做调整。

假设有一个考试信息类TestInfo

class{
    String id;// 报名人员id
    String location;// 考场
    String subject; // 考试科目
}

这其中,location和subject的组合是有限的,因为我们可以将TestInfo信息分为共享信息(比如location和subject)和非共享信息(比如id)。对象池对外提供服务的接口变为pool.get(String key),key由location和subject组成,这样对象池中对象实例的个数与key的可能值构成线性关系。

连接池

连接不是说建就建说关就关的

netty 中涉及到了 线程池管理、连接池管理 以及 如何将这类操作 异步化。当然,一些略复杂,我们从 c3p0 中应该可以学习到,连接池管理 等

线程池

java concurrent 工具类

内存池/内存管理

内存管理

池化的粒度

可以直接对资源池化,比如Socket/Thread(Java语言自带的线程池),也可以对资源封装过的对象进行池化,比如

  1. Jedis 对Socket 封装了Redis通信协议,然后JedisPool 对Jedis 进行池化 Jedis源码分析
  2. EventLoop 对Thread 进行封装,然后EventLoopGroup 对 EventLoop 进行池化

对象池矿建

Apache Commons Pool

异步对象池