我需要在我的应用程序中实现一个计数器映射(例如Map)。但是,该结构应该由多个线程访问。
看来ConcurrentHashMap<Key, Long>
不是适当的解决方案,对不对?
我想到了ConcurrentHashMap<Key, AtomicLong>
。
但是有一个问题-增量请求没有平均分配。很少有最流行的键可以拥有高达95%的对此数据结构的所有增量请求。
据我了解,这将导致并发访问单个AtomicLong
实例,并且应该发生许多锁定,这将在一定程度上降低效率。
问题1:是否有更好的解决方案-也许是更好的数据类型而不是AtomicLong
,它允许短期累积增量或类似的东西?
问题2:我想定期(也许每分钟)将结构持久化到磁盘,并且我想持久化其“实际”状态(所有最近的更新都已解决?)-最直接的方法是什么?
最佳答案
是什么让您认为AtomicLong在内部使用锁?事实并非如此,它主要基于CAS操作。我的建议是使用AtomicLong实施它,并在以后介绍该实现。如果(且仅当)您的计数器将成为瓶颈,请考虑将其替换为任何其他实现。
“我们应该忘记效率低下的问题,大约有97%的时间是这样:过早的优化是万恶之源”-唐纳德·努斯(Donald Knuth)
从状态持久性开始,最简单的方法是序列化地图:
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream objOut = new ObjectOutputStream(out);
objOut.writeObject(map);
objOut.close();