我正在尝试实现用于GPS监控的servlet并尝试创建简单缓存,因为我认为它会比SQL
请求每个Http请求更快。简单方案:
在init()
方法中,我将每辆车的一个点读入HashMap
(车辆ID =钥匙,json =值中的位置)。在那之后,一些请求试图读取这些点并且一些请求尝试更新(一个车辆更新一个项目)。当然我想最小化同步所以我读了javadoc:
http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html
请注意,此实现未同步。如果多个线程同时访问哈希映射,并且至少有一个线程在结构上修改了映射,则必须在外部进行同步。 (结构修改是添加或删除一个或多个映射的任何操作;仅更改与实例已包含的键关联的值不是结构修改。)
如果我是对的,我的任务中没有任何同步,因为我只做“不进行结构修改==更改与实例已经包含的密钥相关联的值”。这是正确的陈述吗?
答案 0 :(得分:0)
使用ConcurrentHashMap,它不使用锁定同步,而是通过原子操作。
答案 1 :(得分:0)
错误。将项添加到哈希映射是一种结构修改(要实现缓存,您必须在某个时刻添加项目)。
使用java.util.concurrent.ConcurrentHashMap。
答案 2 :(得分:0)
如果我理解正确,您有两种类型的请求:
在这种情况下,您可能会尝试同时写入同一个地图两次,这就是文档所指的内容。
如果所有请求都通过相同的代码(例如,只能从一个线程调用的更新方法),则不需要同步。
如果您的系统是多线程的,并且您有多个写入地图的线程或代码片段,则需要在外部同步地图或使用ConcurrentHashMap。
为清楚起见,您需要同步的原因是,如果您有两个线程都尝试更新同一个密钥的JSON值,谁赢了?这要么是偶然的,要么导致异常,或者更糟糕的是,有错误的行为。
每次从两个线程修改相同的元素时,您需要同步该代码,或者更好的是,如果适用,请使用数据结构的线程安全版本。
答案 3 :(得分:0)
如果所有条目都被读入init()
中的hashmap然后只读取/修改 - 那么是,所有其他线程理论上不需要同步,尽管可能会出现一些问题由于线程缓存值,所以ConcurrentHashMap
会更好。
也许不是自己实现缓存,而是使用simple implementation found in Guava library
答案 4 :(得分:0)
缓存不是一个简单的问题 - 但它是一个众所周知的问题。在开始之前,我会仔细测量你确实遇到性能问题,以及缓存是否真正解决了它。你可能认为它应该,你可能是对的。根据情况,你可能也会出现可怕的错误(“抢先优化是所有邪恶的根源”),所以要衡量。
这就是说,不要自己实现缓存,使用库为你做。我对ehcache有很好的经验。