Java 单例返回空对象

Java 单例返回空对象,java,multithreading,singleton,Java,Multithreading,Singleton,我们的项目中有一个缓存实现,我们使用了单例设计模式。类缓存是一个单例类,其中有一个HashMap m。当我们从Hashmap m中获取数据时。返回的内部哈希映射为空。这是随机发生的,我们不知道为什么会发生。我们已经在代码中确保在映射上没有调用remove语句,也没有删除此数据的代码 这方面的任何线索都将非常有用。 提前谢谢 缓存类:- public Class Cache { public static Cache c; private HashMap<String,Has

我们的项目中有一个缓存实现,我们使用了单例设计模式。类缓存是一个单例类,其中有一个HashMap m。当我们从Hashmap m中获取数据时。返回的内部哈希映射为空。这是随机发生的,我们不知道为什么会发生。我们已经在代码中确保在映射上没有调用remove语句,也没有删除此数据的代码

这方面的任何线索都将非常有用。 提前谢谢

缓存类:-

public Class Cache
{
    public static Cache c;
    private HashMap<String,HashMap> m ;
    private Cache()
    {
         m = new HashMap<String,HashMap>();
    }
    public static synchronized Cache getInstance()
    {
        if(c == null) { c = new Cache(); }
        return c;
    }
    public void put(String id,HashMap value)
    {    m.put(id,value);     }
    public HashMap get(String id)
    {    return m.get(id);    }
}
获取值的代码:-

Cache c = Cache.getInstance();
HashMap cityMap = c.get("CITY_CACHE");
//city Map here becomes empty sometimes

这种情况在生产环境中随机发生,我们无法在非生产环境中复制。我怀疑这是因为GC,但没有证据证明这一点。

在同步获取缓存实例时,没有保护内部映射的操作。您应该同步这些操作或使用线程安全的映射实现,例如。

因为我没有您项目的完整背景,我可以建议您执行一些调试步骤。我不认为问题是由于同步。可能是代码的某些部分在获得相同的数据之前删除了数据,这种情况可能在同步或不同步的情况下发生

当您使用键未找到数据时,在日志中打印地图数据。检查数据是否存在于非日志中?显然,我们不能怀疑java中Hashmap的get方法:


是的,GC可能也是原因。

缺少可能必要的同步?你正在使用哈希映射。是的。没有看到任何代码,或者对项目一无所知,这将非常容易回答。猜猜看:你的内部Hashmap是空的。如果您想知道原因:请重新检查您的代码和操作流程,以便更好地理解本文,谢谢您提供的代码还不够。您需要找出其他代码在何处也调用c.putCITY_CACHE、cityMap并覆盖条目。另外,如果Cacheput和Cacheget不同步,您可能会有一个竞争条件。put是从同步包装器类方法调用的,该方法从db获取数据并准备cityMapCan,您可以在GC上提供更多帮助part@NishantModi您可以使用以下参数运行java应用程序,捕获GC日志并检查日志中GC的停止时间。当地图中没有数据时,也要记录详细信息。并比较两个日志的计时-XX:+PrintGCDetails-Xloggc:了解GC日志。谢谢你的建议。我们也试过了。结果是一样的。@NishantModi你找到解决方案了吗?不,还没有,我们只是添加了一个解决方案,当它为空时重新加载它。
Cache c = Cache.getInstance();
HashMap cityMap = c.get("CITY_CACHE");
//city Map here becomes empty sometimes