代码之家  ›  专栏  ›  技术社区  ›  Neil Traft

我应该使用哪一个Java集合来实现线程安全高速缓存?

  •  10
  • Neil Traft  · 技术社区  · 14 年前

    我希望实现一个简单的缓存而不做太多的工作(自然)。在我看来,标准Java集合中的一个应该足够了,还有一点额外的工作。具体来说,我正在存储来自服务器的响应,键可以是请求URL字符串,也可以是从URL生成的哈希代码。

    我原本以为我可以用 WeakHashMap ,但看起来该方法强制我管理要保留的对象,并且任何不使用强引用管理的对象都会立即被清除。我应该试试吗 ConcurrentHashMap 属于 SoftReference 而是价值观?或者这些东西也会被很有侵略性地清理掉吗?

    我现在在看 LinkedHashMap 班级。经过一些修改,MRU缓存看起来很有希望。还有什么建议吗?

    无论我使用哪个集合,我应该尝试手动修剪lru值,还是可以信任vm对回收最近访问的对象有偏见?

    仅供参考,我正在Android上开发,所以我不想导入任何第三方库。我正在处理一个非常小的堆(16到24MB),所以虚拟机可能非常渴望回收资源。我想GC会很有攻击性。

    5 回复  |  直到 14 年前
        1
  •  6
  •   Andrzej Doyle    14 年前

    如果你使用 SoftReference -基于键,虚拟机将(强烈)偏向最近访问的对象。然而,要确定缓存语义是相当困难的——软引用(在weakreference上)提供给您的唯一保证是 OutOfMemoryError 被扔掉。对于一个JVM实现来说,将它们与weakreference处理相同是完全合法的,此时,您可能最终得到一个不缓存任何内容的缓存。

    我不知道Android上是如何工作的,但是对于Sun最近的JVM,可以使用-xx:SoftReflupolicyMSPermb命令行选项来调整SoftReference行为,该命令行选项决定了软访问对象在堆中每MB可用内存中保留的毫秒数。正如您所看到的,这将是非常困难的,以获得任何可预测的寿命行为,与增加的痛苦,这个设置是全局的所有软引用在虚拟机,不能单独调整为个别类的软引用的使用(可能是每个使用将需要不同的参数)。


    制作LRU缓存的最简单方法是扩展LinkedHashMap as described here . 由于您需要线程安全性,最初扩展它的最简单方法是只使用 Collections.synchronizedMap 在该自定义类的实例上,以确保安全的并发行为。

    注意提前优化——除非您需要非常高的吞吐量,否则粗同步理论上的次优开销不太可能是一个问题。好消息是,如果分析显示由于锁争用过多,您的运行速度太慢,那么您就可以获得足够的关于缓存运行时使用的信息,从而能够想出一个合适的无锁替代方案(可能基于ConcurrentHashMap和一些手动lru处理),而不必猜测它的负载配置文件。

        2
  •  5
  •   Denis Tulskiy    14 年前

    LinkedHashMap易于用于缓存。这将创建大小为10的MRU缓存。

    private LinkedHashMap<File, ImageIcon> cache = new LinkedHashMap<File, ImageIcon>(10, 0.7f, true) {
        @Override
        protected boolean removeEldestEntry(Map.Entry<File, ImageIcon> eldest) {
            return size() > 10;
        }
    };
    

    我想你可以用这个Linkedhashmap的同步代理创建一个类。如果我对同步的理解有误,请原谅我。

        3
  •  1
  •   Daniel Voina    14 年前

    www.javolution.org有一些有趣的功能——同步快速收藏。 在您的情况下,它值得一试,因为它还提供一些漂亮的增强小设备作为Android的。

        4
  •  1
  •   aperkins    14 年前

    对于同步, Collections 框架提供同步映射:

    Map<V,T> myMap = Collections.synchronizedMap(new HashMap<V, T>());
    

    然后可以包装它,或者在缓存对象中处理LRU逻辑。

        5
  •  0
  •   Julio Faerman    14 年前

    我喜欢Apache Commons Collections Lrumap