0

我正在处理一个问题声明,需要在 5 分钟后更新作为缓存存储在地图中的对象(来自数据库)

它完成了:

     Map <String, String>hashMapParam = new ConcurrentHashMap<>();
    
     if (!this.hashMapParam.isEmpty() && this.hashMapParam.containsKey(key)) 
            {
                returnValue = this.hashMapParam.get(key);
                
                 if(isThresholdReached(returnValue))
                 {
                    refreshParam(logger); //loads data from db
                    
                 }
               
             }   
private void refreshParam() 
{
 this.hashMapParam.clear(); 
//loads data from db loadData(); }

我是否需要同步方法refreshParam,因为即使在使用 concurrentHashMap 之后,在使用多个线程进行测试时也得到空值?

如果我同步此方法,则实现工作正常。

4

1 回答 1

3

!this.hashMapParam.isEmpty()是冗余检查。

读取器线程会在地图被清除 ( ) 之后和数据库加载条目之前尝试读取一个值。因此,您的方法似乎不正确。在某个时间点,你是空的。hasMapParam.clear()hashMapParam

ConcurrentHashMap 允许多个线程同时写入映射。当您像您一样在地图上进行两次操作(清除和加载)时,它对您没有帮助。

当刷新正在进行时,同步该refreshParam方法不会阻止其他线程从映射中读取。

您必须同步,hashMapParam调用者也必须这样做。这违背了使用 ConcurrentHashMap 的全部意义。

我建议你:

  1. 使并发哈希映射volatile

  2. 使用从 DB 中新加载的数据创建一个新的 ConcurrentHashMap

  3. 使用新引用重新分配对并发哈希映射的引用。

    this.hashMapParam = <new_concurent_hash_map_instance_with_latest_mappings>

请参阅:如何在客户端读取 HashMap 时刷新它


(您尚未向我们展示如何将数据加载到地图中)

如果您不想同步刷新方法...

您想一次性加载所有项目吗?是否有跨多个条目的完整性要求?您可以在不清除地图的情况下加载条目吗?在这种情况下,您必须找到已删除的条目并将其从地图中删除。

于 2020-06-24T09:17:31.377 回答