0

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

在该init()方法中,我将每辆车的一个点读入HashMap(vehicle id = key, location in json = value) 。之后,一些请求尝试读取这一点,一些请求尝试更新(一辆车更新一项)。当然,我想尽量减少同步,所以我阅读了 javadoc: http ://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html

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

如果我是对的,我的任务中没有任何同步,因为我只做“不是结构修改==更改与实例已包含的键关联的值)”。这是一个正确的说法吗?

4

5 回答 5

0

使用 ConcurrentHashMap 它不通过锁使用同步,而是通过原子操作。

于 2013-02-26T19:45:38.720 回答
0

错误的。将项目添加到哈希映射是一种结构修改(并且要实现缓存,您必须在某个时候添加项目)。

使用 java.util.concurrent.ConcurrentHashMap。

于 2013-02-26T19:46:01.183 回答
0

如果我理解正确,您有两种类型的请求:

  • 从缓存中读取
  • 写入缓存(更新值)

在这种情况下,您可能会尝试同时写入同一个地图两次,这就是文档所指的内容。

如果所有请求都通过同一段代码(例如,只能从一个线程调用的更新方法),您将不需要同步。

如果您的系统是多线程的,并且您有多个线程或一段代码写入地图,您将需要在外部同步您的地图或使用 ConcurrentHashMap。


为清楚起见,您需要同步的原因是,如果您有两个线程都试图更新同一个键的 JSON 值,那么谁赢了?这要么是偶然的,要么是导致异常,或者更糟糕的是,错误的行为。

每当您从两个线程修改相同的元素时,您都需要在该代码上进行同步,或者更好的是,如果适用的话,使用数据结构的线程安全版本。

于 2013-02-26T19:48:11.140 回答
0

Caching is not an easy problem - but it is a known one. Before starting, I would carefully measure wheter you really do have a performance problem, and whether caching actually solve it. You may think it should, and you may be right. You may also be horrendously wrong depending on the situation ("Preemptive optimization is the root of all evil"), so measure.

This said, do not implement a cache yourself, use a library doing it for you. I have personnaly good experience with ehcache.

于 2013-02-26T20:10:14.170 回答
0

如果所有条目都被读入hashmap,init()然后只读取/修改 - 那么是的,理论上所有其他线程都不需要同步,尽管由于线程缓存值可能会出现一些问题,所以ConcurrentHashMap会更好。

也许不是自己实现缓存,而是使用Guava 库中的简单实现

于 2013-02-26T19:50:32.897 回答