2

我正在编写一个消息传递门面,它接收任意 POJO 并以 JSON 格式通过网络发送它们,工作流程如下:

  1. 用户调用MessagingFacade.sendMessage(Object)
  2. 从池中借用一个 ByteBuffer,我们将把消息序列化到这个缓冲区中
  3. 通过调用将 POJO 转换为 JSONJsonSerializer.serialize(Object, ByteBuffer)
  4. 通过网络发送已编码的消息Transport.send(ByteBuffer),保留对将在消息发送时通知的承诺的引用
  5. 将回调附加到 Promise 以在 ByteBuffer 被写入线路后将其返回到池中
  6. MessagingFacade.sendMessage(Object)调用返回

这是池化 ByteBuffers 的一个相对简单的用例,因为我们可以调用clear()以在对象返回池时重置状态。


我没有编写自己的对象池,而是尝试利用 Apache 中已经提供的对象池commons-pool。然而,似乎有一个相当大的警告GenericObjectPoolSoftReferenceObjectPool......

在借用/归还对象时,这两个池使用hashCode()和/或equals()来标识关联的PooledObject<ByteBuffer>. ByteBuffer鉴于equals()hashCode()实现涉及评估底层byte数组的内容,这对 有非常实际的影响:

  1. 对象清理 - 当对象ByteBuffer返回池时,它的状态为“已清理”。这仅涉及调用ByteBuffer.clear(). 这不会将数组中的所有字节清零,这意味着返回 ,equals()与借用时会hashCode()给出不同的结果。ByteBuffer
  2. 评估速度 - 鉴于我正在ByteBuffer以最大消息大小 (1MB) 的容量汇集实例,评估两者hashCode()并且equals()必须线性遍历这个非常大的数组

Apache commons-pool 实现似乎不适合任何用例,其中(a)该类具有昂贵的equals()实现hashCode()或(b)hashCode()在清理后不会产生稳定的结果。

GenericObjectPool为这个用例制作或工作的唯一可行选择SoftReferenceObjectPool似乎是将其包装ByteBuffer在另一个使用身份相等/哈希码逻辑的类中。

这是可行的,但考虑到这个用例的普通程度,感觉有点麻烦。这种方法有更好的选择吗?


最后一点;由于 和 的不稳定性,equals()实际上hashCode()会从 中获得异常GenericObjectPool,因为池认为您正在尝试返回一个从未从池中借来的对象:

java.lang.IllegalStateException: Returned object not currently part of this pool
 at org.apache.commons.pool2.impl.GenericObjectPool.returnObject(GenericObjectPool.java:537)
 ...
4

1 回答 1

2

您所指的限制已在 JIRA 问题 POOL-283 和 POOL-284 中确定,这些问题已在 Commons Pool 的 2.4.1 版中得到解决。尝试升级到版本 2.4.1。

于 2015-06-12T14:00:31.600 回答