享元模式中this确保对象池为实例私有且线程安全,核心是ConcurrentHashMap+computeIfAbsent+this绑定的本地池,禁止static池和享元持有this引用。

在享元模式中,this 关键字本身并不直接参与对象池的线程安全归入操作;它的作用是明确指向当前工厂实例,从而确保池容器(如 Map 或 ConcurrentHashMap)的访问和更新发生在同一个、有状态的工厂对象上下文中。真正实现“安全归入”的核心在于:**用线程安全的集合 + 正确的初始化与检查逻辑 + this 引用所绑定的实例级池**。
确保池容器是实例私有且线程安全的
享元工厂必须维护一个属于自身的对象池,不能使用静态池(除非明确设计为全局共享且已做好同步)。this 指向的正是这个唯一实例,因此所有对池的操作都天然限定在其生命周期内。
- 声明为
private final Map<Key, Flyweight> pool = new ConcurrentHashMap<>();—— 利用ConcurrentHashMap的原子性方法(如computeIfAbsent)避免显式锁 - 不要用
static Map,否则 this 失去意义,多个工厂实例会竞争同一池,破坏封装和可控性 - 构造器中不初始化池以外的共享状态,保证 this 的纯净性
用 this + computeIfAbsent 实现“获取或创建并安全存入”
这是最常用也最安全的方式:利用 ConcurrentHashMap.computeIfAbsent() 的原子语义,在 this 所指的池上完成“查无则建、建完即存、并发安全”的闭环。
- 写法示例:
return pool.computeIfAbsent(key, k -> new ConcreteFlyweight(k)); - 该调用内部已保证:同一 key 不会重复构造,也不会出现两个线程同时 put 同一新对象的情况
- this 在这里确保了 pool 是当前工厂实例的成员,而非其他对象的——这是“本地池化”的前提
避免在构造享元时反向持有 this 引用
享元对象通常应是轻量、无状态(或仅含内在状态)的。若在享元内部保存对 this(工厂)的引用,可能引发内存泄漏或并发干扰。
- 享元不应调用工厂的 add/remove 方法,也不应知道池的存在
- 工厂负责管理生命周期;享元只专注业务逻辑,通过参数接收外在状态(extrinsic state)
- 若需回调(极少见),应通过接口解耦,而非直接传 this
需要显式归入时(如享元可回收),仍依托 this 管理
某些场景下享元可能被显式释放(如连接池中的连接),此时归入操作仍必须通过 this 调用工厂的归还方法,确保操作落在正确的池实例上。
- 提供
void returnToPool(Flyweight flyweight)方法,内部调用this.pool.put(key, flyweight) - 配合引用计数或弱引用机制时,计数器也必须是 this 的成员变量,而非静态
- 调用方必须持有对该工厂实例(this)的引用,才能正确归还——这正体现了“本地池化”的约束

















