实例缓存清理

我有一个对象/类ClassA,它的实例需要使用成千上万个键进行缓存(我们称其为cache1)。 但是实际上,ClassA的实例数限制为数百。

所以我想通过重用ClassA实例来压缩缓存的堆使用情况。

一个简单的方法是使用一个简单的池(也许这不是一个普通池):

final class ClassA {

    private byte[] bytes;
    private static final ConcurrentHashMap<String,ClassA> instancePool = new ConcurrentHashMap<>();

    private ClassA(String bigString) {
        bytes = bigString.getBytes();
    }

    public static ClassA getInstance(String key) {
        instancePool.putIfAbsent(key,new ClassA(key));
        return instancePool.get(key);
    }

    public byte[] getBytes() {
        return bytes;
    }
}

有效。但是问题在于实例可以更改,甚至不经常更改。 缓存可以过期,但instancePool不能过期。因此它将容纳越来越多的无用实例,对我而言,这就像一颗定时炸弹。

所以我想从池中清除无用的实例(不由cache1引用)。 一个简单的想法是使用另一个cache(cache2)而不是instancePool。并给它更长的到期时间。但这似乎不是理想的方法。

这似乎是一个常见问题。有库可以这样做吗?

xiaozhuhechaohong 回答:实例缓存清理

如果要根据时间使对象过期,可以使用jodah中的ExpiringMap

赞:

Map<String,Integer> map = ExpiringMap.builder().expiration(30,TimeUnit.SECONDS).build();
,

首先,我想指出实施中的问题:

  1. String是不可变的,因此byte[] bytes可以是最终的,并封装在ClassA
  2. getBytes()破坏了OOP封装原理。它应该检索byte[] bytes的副本。
  3. instancePool.putIfAbsent(key,new ClassA(key));每次都在此处创建ClassA的新实例,即使该实例存在并且不会放入缓存中。
  4. ClassA getInstance(String key)如果key是大String,那么为什么要创建内部byte[]的副本?为什么不只使用String本身并使用key.charAt()
  5. bytes = bigString.getBytes();使用Charset cs = Charset.defaultCharset();,因此如果key不包含ASCII字符,您可能会感到惊讶。

每次调用byte[] bytes时都不能自动检索getBytes(),也不能复制它。因此,建议您使用不可变对象。在这种情况下,项目的到期不会有问题,因为每次应更改时,都将从缓存中删除该项目。

我在想什么。大概是这样的:

public final class ClassA {

    private static final Map<UUID,ClassA> POOL = new HashMap<>();

    private final UUID id;
    private final byte[] data;

    public static synchronized ClassA getInstance(UUID id,byte[] data) {
        if (POOL.containsKey(id))
            return POOL.get(id);

        ClassA obj = new ClassA(id,data);
        POOL.put(id,obj);
        return obj;
    }

    private ClassA(UUID id,byte[] data) {
        this.id = id;
        this.data = Arrays.copyOf(data,data.length);
    }

    public int getSize() {
        return data.length;
    }

    public byte getByteAt(int pos) {
        return data[pos];
    }

}
本文链接:https://www.f2er.com/3154588.html

大家都在问