8

我正在编写一个编解码器来处理使用定制的有线协议通过 TCP 发送的消息。在解码过程中,我创建了许多Strings、BigDecimals 和日期。客户端-服务器访问模式意味着客户端发出请求然后解码数千条响应消息是很常见的,这会导致大量重复 String的s,BigDecimals等。

因此,我创建了一个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));

我的问题:我正在使用InternPoolforBigDecimal但我是否应该考虑也使用它String 而不是 String'intern()方法,我认为该方法使用 PermGen 空间?使用 PermGen 空间有什么好处?

4

2 回答 2

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()以避免错误的代码弄乱它。

于 2010-05-19T11:39:03.197 回答
3

JVM 的String.intern()池可能会更快。AFAIK,它是在本机代码中实现的,因此它应该WeakHashMap比使用and实现的池更快并且使用更少的空间WeakReference。您需要进行一些仔细的基准测试来确认这一点。

但是,除非您有大量长期存在的重复对象,否则我怀疑实习(在 permGen 中或在您自己的池中)会产生很大的不同。如果唯一对象与重复对象的比例太低,那么实习只会增加活动对象的数量(使 GC 花费更长的时间)并由于实习的开销而降低性能等等。因此,我还主张对“实习生”与“非实习生”方法进行基准测试。

于 2010-05-19T12:14:02.363 回答