Java 如何使用LinkedHashMap中类似的功能实现ConcurrentHashMap?

Java 如何使用LinkedHashMap中类似的功能实现ConcurrentHashMap?,java,performance,multithreading,concurrenthashmap,linkedhashmap,Java,Performance,Multithreading,Concurrenthashmap,Linkedhashmap,我将LinkedHashMap与accessOrdertrue一起使用,并允许在任何时候最多有500个条目作为数据的LRU缓存。但由于可伸缩性问题,我想继续讨论一些线程安全的替代方案ConcurrentHashMap在这方面似乎不错,但缺少accessOrder和RemoveedStantry(Map.Entry e)的功能,这些功能可以在LinkedHashMap中找到。任何人都可以指向一些链接或帮助我简化实现 将地图包装在一个Collections.synchronizedMap()中。如果

我将
LinkedHashMap
accessOrder
true一起使用,并允许在任何时候最多有500个条目作为数据的LRU缓存。但由于可伸缩性问题,我想继续讨论一些线程安全的替代方案
ConcurrentHashMap
在这方面似乎不错,但缺少
accessOrder
RemoveedStantry(Map.Entry e)
的功能,这些功能可以在
LinkedHashMap
中找到。任何人都可以指向一些链接或帮助我简化实现

将地图包装在一个
Collections.synchronizedMap()
中。如果需要调用其他方法,则在从该调用返回的映射上同步,并在原始映射上调用原始方法()。这同样适用于迭代键等。

我最近在
ConcurrentHashMap
中做了类似的事情,其中CacheEntry包装了实际项并添加了缓存逐出统计信息:过期时间、插入时间(对于FIFO/LIFO逐出)、上次使用时间(对于LRU/MRU逐出)、命中次数(对于LFU/MFU逐出),等。实际逐出是同步的,并创建一个
ArrayList
,并使用逐出策略的适当比较器对其执行Collections.sort()。因为这很昂贵,所以每次逐出都会删除缓存条目的底部5%。不过,我相信性能调整会有所帮助

在你的情况下,因为你在做FIFO,你可以保留一个单独的。将对象添加到ConcurrentHashMap时,对该对象执行ConcurrentLinkedQueue.add()操作。如果要逐出条目,请执行ConcurrentLinkedQueue.poll()以删除最旧的对象,然后将其从ConcurrentHashMap中删除


更新:这方面的其他可能性包括Java集合和Java 1.6

您是否尝试过使用ehcache等众多缓存解决方案之一?
您可以尝试将LinkedHashMap与ReadWriteLock一起使用。这将为您提供并发读访问。

您提到希望使用“线程安全”替代方案解决可伸缩性问题。这里的“线程安全”意味着该结构能够容忍并发访问的尝试,因为在没有外部同步的情况下,它不会因并发使用而受到损坏。然而,这种容忍度并不一定有助于提高“可伸缩性”。在最简单的方法中——尽管通常是错误的——您将尝试在内部同步您的结构,但仍然保留非原子检查,然后执行不安全的操作

LRU缓存至少需要了解总体结构。他们需要一些诸如成员数量或成员大小之类的信息来决定何时退出,然后他们需要能够将退出与读取、添加或删除元素的并发尝试相协调。试图减少并发访问“主”结构所需的同步会与逐出机制相冲突,并迫使逐出策略在保证方面不那么精确


目前被接受的答案提到“当你想逐出一个条目时”。这就是问题所在。如何知道何时要逐出条目?您还需要暂停哪些操作才能做出此决定?

这可能看起来很旧,但至少为了我自己的历史跟踪,我将在这里添加我的解决方案:我将ConcurrentHashMap与WeakReference的K->子类ConcurrentLinkedQueue相结合,以及一个接口,该接口基于K定义值对象的反序列化,以正确运行LRU缓存。队列包含强引用,GC将在适当的时候从内存中逐出这些值。跟踪队列大小涉及AtomicInteger,因为您无法真正检查队列以确定何时退出。缓存将处理从队列中移出/添加到队列的操作,以及映射管理。如果GC从内存中逐出该值,则反序列化接口的实现将处理返回该值的操作。我还有另一个实现,涉及到假脱机到磁盘/重新读取假脱机的内容,但这比我在这里发布的解决方案慢得多,因为我需要同步假脱机/读取。

当您使用另一个数据结构以及concurrenthashmap时,在concurrenthashmap中添加新项和添加其他数据结构等操作的原子性,如果没有诸如ReadWriteLock之类的额外同步,将无法保证,这将降低性能

Aaron这将恶化我的可伸缩性问题。因为地图的更新本质上是连续的。ConcurrentHashMap具有这样的功能,即多个用户可以同时更新映射。ConcHM具有一些不容易映射到LinkedHM的特定属性(即,只要哈希不映射到同一段键,它就允许并发插入)。如果需要保持插入顺序,则无法进行此优化。你必须决定哪一个对你更重要。你的建议似乎很像我需要的。这意味着我有一些开销来保持其他元素,这些元素将消耗和映射集相同的大小。无论如何,这对我来说很好。我知道这已经有一段时间了,但我找到了你的答案,你能告诉我当你得到被逐出条目的ArrayList时,你如何从ConcurrentHashMap中删除它们吗?您是否迭代映射。条目检查值是否相同,然后使用其键将其从映射中删除?还是我错过了什么而你却用另一种方式去做?还没有。但是EHcache将是我的另一个选择。我们已经尝试了使用LinkedHashMap(maxSize,true)的ReentrantReadWrite锁,但是您会得到ConcurrentModificationException(get将修改映射结构),并且性能远不如ConcurrentHashMap。这是一个真正困难的问题。我们一直在努力在谷歌的收藏中解决这个问题,但仍然没有完全解决。但我们将…类似的问题:谢谢,很高兴将您的解决方案添加到