我有一个Java应用程序,其中我在内存中的哈希映射中维护其他服务器的一组IP。哈希映射包含服务器实例ID到服务器IP地址之间的映射。我还在数据库中维护这些服务器信息以实现持久性。
我试图解决一个简单的问题,我只需要缓存在内存中的服务器信息,以便更快地访问。所以我使用了hashmap。我需要确保内存中的服务器信息不过时,缓存中的所有服务器都有响应。
所以我创建了两个单独的后台守护线程
在这里,第一个线程经常运行15秒,第二个DB线程每5分钟运行一次。
由于两个线程都在更新这里的缓存,我已经使用了并发HashMap,因为它将被同步。即使这样,当我阅读多篇文章、文档和一些stackoverflow帖子时,我看到多个线程更新hashmap将是有风险的,比如当一个线程迭代hashmap时,其他线程可能会被触发并开始更新hashmap。
那么我如何在这里使用不同的方法来解决这个问题,这样我就不会在应用程序性能、时间和空间复杂性方面打扰JVM,并确保我的hashmap中一直只有响应式服务器条目。
并发HashMap保证这一点:
视图的迭代器是一个弱一致的迭代器,它永远不会抛出并发修改异常,并保证遍历迭代器构造时存在的元素,并且可以(但不能保证)反映构造后的任何修改。
这意味着在最坏的情况下,一个线程所做的更新直到下一次迭代才会被第二个线程看到。让我们看看这对您的应用程序意味着什么:
如果同步线程在ping线程运行时添加了一个新服务器,则此迭代可能不会ping它。它将仅在15秒后的下一次迭代中ping。只要您考虑到这种行为,这似乎不是问题(即如果您不运行第三个线程,该线程删除过去15秒内未ping的任何内容或类似内容)
如果同步线程在ping进行时删除了服务器,则服务器可能仍在ping,但服务器的记录仍将从缓存中删除。同样,不是问题。
如果ping线程在同步进行时删除服务器,同步线程可能仍会在缓存中看到该服务器。同样,我认为这不是问题。
如果您需要确保数据展示一致性,并且每个线程都需要有最新的数据视图,请使用Collection. synizedMap(map)。如果性能至关重要,并且每个线程只将数据插入到映射中,读取发生的频率较低,请使用ConCurrentHashMap。
有一篇很好的文章解释了地图的内部深层概念/java实际用例的工作:
http://java.dzone.com/articles/java-7-hashmap-vs
希望这有帮助。