servlet中的hashmap缓存

时间:2013-02-26 19:39:44

标签: java caching servlets hashmap

我正在尝试实现用于GPS监控的servlet并尝试创建简单缓存,因为我认为它会比SQL请求每个Http请求更快。简单方案:

init()方法中,我将每辆车的一个点读入HashMap(车辆ID =钥匙,json =值中的位置)。在那之后,一些请求试图读取这些点并且一些请求尝试更新(一个车辆更新一个项目)。当然我想最小化同步所以我读了javadoc: http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html

  

请注意,此实现未同步。如果多个线程同时访问哈希映射,并且至少有一个线程在结构上修改了映射,则必须在外部进行同步。 (结构修改是添加或删除一个或多个映射的任何操作;仅更改与实例已包含的键关联的值不是结构修改。)

如果我是对的,我的任务中没有任何同步,因为我只做“不进行结构修改==更改与实例已经包含的密钥相关联的值”。这是正确的陈述吗?

5 个答案:

答案 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有很好的经验。