【问题标题】:Best approach to store a set of static String values存储一组静态字符串值的最佳方法
【发布时间】:2018-06-21 19:04:38
【问题描述】:

我需要从 odata uri 中检索查询参数,比如 clIdclCtxclName,并在整个程序中使用它们很多课。在我们定制的客户端框架中,每次检索查询参数都是一个昂贵的过程。每个请求一次检索和存储参数并在整个程序中使用相同参数的最佳方法是什么?

我的想法是创建一个带有静态 Java 映射的单例类,如下所示。我第一次可以检索它们并将它们存储在地图中以供以后使用。

也想知道我的方法是否有任何问题,例如内存泄漏或缺点。

public class ClientContainer {

  private static Map<String,String> clientMap;
  private static ClientContainer instance;

  private ClientContainer(){}

 public static ClientContainer getInstance(){
    if(instance == null){
        instance = new ClientContainer();
    }
    return instance;
  }

  private void updateClientMap(HashMap<String,String> clientMap){
    if(this.clientMap==null){
        this.clientMap =clientMap;
    }
  }

  private HashMap<String,String> getClientMap(){
     return this.clientMap;
   }
}

【问题讨论】:

  • 如果您已经知道参数名称并且它们不是动态的,那么使用地图也很昂贵。我想,我宁愿用好的老豆,它又快又干净。此外,根据系统背后的实现,您可能只是用另一个地图替换地图,在这种情况下,建议的方法将是有害的。
  • Victor,我检索到的查询参数不是普通的 Java 映射。要获得带有这些参数的 Java Map,大约需要进行 4 次转换(scala 数据到 Java 数据)。我必须在不同的类中重复此过程 10-11 次。由于这会影响程序的性能,因此我需要一种有效且优化的方法将它们作为一次性步骤存储在程序中的某个位置并以简单的方式获取它们每当我需要它们时。
  • 参数有多少?知道提前知道他们的名字吗?如果他们很少而且你认识他们,我会用豆子。
  • 在这种情况下,我喜欢你的解决方案,但你想检查你是否映射调用 volatile 并且如果除了 volatile 之外是不可变的和最终的,你会更舒服。考虑到你添加一个客户端密钥也是。
  • 感谢维克多的建议。最好使用 bean,因为我的方法有问题,并且可能会导致实时内存泄漏,这更加昂贵。

标签: java performance collections singleton


【解决方案1】:

也想知道我的方法是否有内存泄漏之类的问题 或缺点。

1) 您的ClientContainer 类仅存储一个客户端的参数。
您使用Map&lt;String,String&gt;(参数值)而不是Map&lt;Client, Map&lt;String, String&gt;&gt;(参数值和客户端的所有值)。
由于您可以使用单例模式对类进行一次实例化,因此您只能存储不超过一个客户端请求的数据。

2) 这样一来,请求的生命周期(参数值)将是无限的。
Map 确实永远不会被垃圾收集,因为它被从未有机会被垃圾收集的单例实例引用。

因此,如果您保留单例模式,您至少应该根据客户端考虑key-values,并且您还应该考虑在每次完全处理请求时清理缓存以避免内存泄漏。

但如果我是你,我可能会使用另一种解决方案:

  • 要么我将 Map 一次性创建为局部变量:在我收到请求时,然后我会将其显式传递给每个需要它的方法。

  • 如果每个请求都由特定线程处理,我会使用 ThreadLocal 来存储 Map。

请注意,我更喜欢第一种方式,它清楚地暴露了方法的依赖关系。
另请注意,如果要使用的字段数量稳定且已知,则使用Map 并不是最好的选择:使用自定义类可能更清晰、可读且更健壮。

【讨论】:

  • 感谢大卫的明确解释。这真的很有帮助。
  • @Lokesh Reddy 如果对您有帮助,我很高兴。
  • 为此:要么我将 Map 作为一个局部变量创建一次:在我收到请求的时候,然后我会明确地将它传递给每个需要它的方法。跨度>
  • 此答案中描述的集中式缓存也将受益于易失性,可能是最终的,并具有额外的逻辑来确保地图是可变的。地图本身不需要同步,只要它是只读的。
  • 同样,祝你好运。但只是为了澄清,是的,如果有 2 个级别,您需要同步。但对于最后一个级别不是。在那种情况下,有 2 张地图,我指的是内部地图。
【解决方案2】:

如果您在多线程环境中使用 ClientContainer 类,那么使 getInstance() 方法线程安全以避免重复构造函数是有意义的。为避免内存泄漏,您可以使用 Wea​​kHashMap 代替 HashMap。

【讨论】:

    猜你喜欢
    • 2016-01-03
    • 1970-01-01
    • 2012-10-16
    • 2023-03-17
    • 1970-01-01
    • 2013-03-02
    • 1970-01-01
    • 2011-08-28
    • 1970-01-01
    相关资源
    最近更新 更多