Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在多线程环境中使用HashMap进行定期更新_Java_Hashmap_Synchronization_Concurrenthashmap - Fatal编程技术网

Java 在多线程环境中使用HashMap进行定期更新

Java 在多线程环境中使用HashMap进行定期更新,java,hashmap,synchronization,concurrenthashmap,Java,Hashmap,Synchronization,Concurrenthashmap,我有一个Java应用程序,在该应用程序中,我在内存中的哈希映射中维护其他服务器的IP集。哈希映射包含服务器实例ID到服务器ip地址之间的映射。我还将这些服务器信息保存在数据库中,以便持久化 我试图解决一个简单的问题,我只需要将服务器信息缓存在内存中,以便更快地访问。所以我使用了hashmap。我需要确保内存中的服务器信息没有过时,缓存中的所有服务器都有响应 因此,我创建了两个独立的后台守护进程线程,其中 一个线程,从hashmap获取每个条目并ping所有条目。如果任何服务器没有响应,那么它将

我有一个Java应用程序,在该应用程序中,我在内存中的哈希映射中维护其他服务器的IP集。哈希映射包含服务器实例ID到服务器ip地址之间的映射。我还将这些服务器信息保存在数据库中,以便持久化

我试图解决一个简单的问题,我只需要将服务器信息缓存在内存中,以便更快地访问。所以我使用了hashmap。我需要确保内存中的服务器信息没有过时,缓存中的所有服务器都有响应

因此,我创建了两个独立的后台守护进程线程,其中

  • 一个线程,从hashmap获取每个条目并ping所有条目。如果任何服务器没有响应,那么它将从hashmap中删除该条目
  • 另一个线程基本上将数据库条目与这个hashmap缓存同步。因此,它查询数据库中的所有条目,删除数据库中不存在的hashmap中的条目,对于数据库中的新条目,它ping每个条目并添加到hashmap中
这里第一个线程经常运行,比如每15秒运行一次,第二个DB线程每5分钟运行一次

因为这两个线程都在更新缓存,所以我使用了ConcurrentHashMap,因为它将被同步。即使这样,当我阅读多篇文章、文档和一些stackoverflow文章时,我发现多个线程更新hashmap是有风险的,就像当一个线程在hashmap上迭代时,另一个线程可能会被触发并开始更新hashmap


因此,我如何在这里使用不同的方法来解决这个问题,这样我就不会在应用程序性能、时间和空间复杂性方面干扰JVM,并确保我的hashmap中始终只有响应服务器条目。

ConcurrentHashMap保证了这一点:

视图的迭代器是一个“弱一致性”迭代器,它永远不会 抛出ConcurrentModificationException,并保证遍历 元素在构造迭代器时存在,并且可能 (但不保证)反映本协议之后的任何修改 建筑

这意味着在最坏的情况下,一个线程所做的更新在下一次迭代之前不会被第二个线程看到。让我们看看这对您的应用程序意味着什么:

如果在ping线程运行时,同步线程添加了一个新服务器,那么在这个迭代中可能不会ping它。只有在15秒后的下一次迭代中才会ping。只要考虑到这种行为(即,如果您没有运行第三个线程来删除在过去15秒内没有ping过的任何内容或类似内容),这似乎不是问题

如果在ping过程中同步线程删除了服务器,则可能仍会ping该服务器,但仍会从缓存中删除该服务器的记录。再说一次,这不是问题


如果ping线程在同步过程中删除服务器,则同步线程仍可能在缓存中看到该服务器。再说一次,我认为这不是问题

如果需要确保数据一致性,并且每个线程都需要有最新的数据视图,请使用Collections.synchronizedMap(映射)。如果性能非常关键,并且每个线程只向映射中插入数据,读取的频率较低,则使用ConcurrentHashMap

有一篇很好的文章解释了java中映射的内部深层概念/使用真实用例的过程:


希望这能有所帮助。

您能澄清您的担忧吗?在hashmap上迭代的多线程不一定是问题。你担心什么?还有,使用两个线程有什么理由吗?为什么不让一个线程操作缓存呢?我不认为两个线程在hashmap上迭代会有问题,但我关心的是一个线程正在添加一个条目,另一个线程正在添加/删除条目。虽然这些操作非常罕见,但由于我们正在从两个不同的实体更新hashmap,应用程序的性能会受到影响吗?不会,不会有性能问题。感谢链接。感谢您的回复。很高兴收到您的回复。如果我们经常从ConcurrentHashMap中添加/删除,会不会对该应用程序的性能造成影响?根据techboost提供的链接,ConcurrentHashMap在性能方面更快、更清晰。您对此有何看法?您的应用程序所做的一切都会带来相关的性能成本。如果您需要准确估计几种技术替代方案的性能,我建议您自己进行基准测试。但一般来说,Java的并发数据结构确实非常优秀,而且比自己锁定要好。