我正在编写一个Codec来处理使用定制有线协议通过TCP发送的消息。在解码过程中,我创建了许多String
s,BigDecimal
和日期。客户端 - 服务器访问模式意味着客户端发出请求然后解码数千条响应消息是很常见的,这会导致大量重复 String
,{{ 1}} s等。
因此我创建了一个BigDecimal
类,允许我实习每一类对象。在内部,池使用InternPool<T>
。例如:
WeakHashMap<T, WeakReference<T>>
我的问题:我正在InternPool<BigDecimal> pool = new InternPool<BigDecimal>();
...
// Read BigDecimal from in buffer and then intern.
BigDecimal quantity = pool.intern(readBigDecimal(in));
使用InternPool
但是我应该考虑将其用于BigDecimal
,而不是 String
的{ {1}}方法,我相信使用PermGen空间?使用PermGen空间有什么好处?
答案 0 :(得分:5)
如果您已经有这样的InternPool
类,那么认为使用它比为字符串选择不同的实习方法更好。特别是因为String.intern()
似乎提供了比实际需要更强大的保证。您的目标是减少内存使用量,因此实际上不需要在JVM的生命周期内实现完美的实习。
另外,我会使用Google Collections MapMaker
创建InternPool
以避免重新创建轮子:
Map<BigDecimal,BigDecimal> bigDecimalPool = new MapMaker()
.weakKeys()
.weakValues()
.expiration(1, TimeUnits.MINUTES)
.makeComputingMap(
new Function<BigDecimal, BigDecimal>() {
public BigDecimal apply(BigDecimal value) {
return value;
}
});
这将为您提供(正确实现)弱键和值,线程安全性,旧条目的自动清除以及非常简单的界面(简单,众所周知的Map
)。确保你也可以使用Collections.immutableMap()
来包装它,以避免错误的代码搞乱它。
答案 1 :(得分:3)
JVM的String.intern()
池可能会更快。 AFAIK,它是用本机代码实现的,因此应该比使用WeakHashMap
和WeakReference
实现的池更快,占用的空间更少。您需要进行一些仔细的基准测试以确认这一点。
但是,除非你有大量长期存在的重复对象,否则我怀疑实习(无论是在permGen中还是在你自己的游泳池中)会产生很大的不同。如果唯一对象与重复对象的比率太低,那么实习只会增加活动对象的数量(使GC需要更长时间)并由于实习的开销而降低性能,等等。因此,我还提倡对“实习生”与“实习生”方法进行基准比较。