【问题标题】:Java Hashtable many accesses problemJava Hashtable 多次访问问题
【发布时间】:2010-07-13 08:19:04
【问题描述】:

我正在开发工具,它采用 Java 代码并生成代码,以估计基本块、循环和方法的执行时间。在执行了某个块之后,我们就可以使用我们的工具了。程序模型存储在下一个表示中

static Hashtable<String, Hashtable<Integer, Hashtable<String, pair>>> method2Data = new Hashtable<String, Hashtable<Integer, Hashtable<String, pair>>>();

static Hashtable<String, Vector<String>> class2Method = new Hashtable<String, Vector<String>>();

一个方法所花费的时间

 public static void addBlock(int id, double time, String meth, String thread);

但我还有下一个问题。在每次调用 addBlock 时,我们都会从 method2data 中获取一些东西。因为我们可以有像

这样的代码
for (int i = 0; i < n; i++)
  for (int j = 0; j < n; j++)
    for (int k = 0; k < n; k++) {
      addBlock(0,...);
      addBlock(m,...);
    }

我们经常调用 addBlock。 不幸的是,在我们的 claster 上工作了一段时间后,程序就停止了工作。它看起来仍然像进程,但不占用任何 CPU。我发现,如果我删除从 method2data 中获取某些内容的代码,那么一切正常。所以,我猜,对 Hashtable 的访问存在一些问题。有什么好的想法吗?

多亏了大家,看来我在并发访问的情况下遇到了死锁,并且在没有并发访问的情况下可能会耗尽内存。

【问题讨论】:

  • 可以同时调用 addBlock 吗?如果是,是否有一些锁或同步块?
  • 是的,他们可以,但我记得 Hashtable 允许并发访问。

标签: java hashtable


【解决方案1】:

如果您使用的是 Java5 或更高版本,则不应使用Hashtable,而应使用ConcurrentHashMap,它通过锁条带提供了更好的可扩展性,因此可能会立即解决问题(以防出现死锁或饥饿问题) ,这是基于您的 - 不完整 - 描述的可能性)。在同一行,不要使用Vector,而是使用一些List 实现。 HashtableVector 都是旧的集合实现,它们是同步的,在这个 Vector 的情况下可能是不必要的。

[更新] 正如@finnw 正确指出的那样,即使 ConcurrentHashMap 似乎 有所帮助,您也不能确定根本原因是否真的得到了解决。需要进行彻底的分析和测试,以查看您的代码是否实际上是线程安全的。如果没有看到addBlock() 中的代码,我们无法就此得出结论。 [/更新]

另外,正如其他人所指出的,将配置文件数据保存在内存中对于大型程序来说并不是一个好主意,因为这可能会影响您尝试测量的性能特征,甚至可能会耗尽内存。

【讨论】:

  • -1。这是很危险的,因为如果出现死锁,ConcurrentHashMap 的发生频率会降低,从而使错误看起来已修复,但实际上并非如此。
  • @finnw,它可能发生的频率较低,或者可能完全停止发生 - 没有看到具体代码就不可能说。你说得对,这是一种风险,我更新了我的答案以澄清。
  • 谢谢你,在我想了这么多想法之后,我需要重写这部分代码并确保它是线程安全的。
【解决方案2】:

只是一个偶然的想法:你可能内存不足了吗?

尝试使用 -Xmx512m 启动您的应用程序,以允许 512 MB 的堆空间。

内存不足通常会减慢你的进程,直到它看起来什么都不做,因为它在每一条指令之后都会调用垃圾回收。

【讨论】:

  • 嗯,这是我的第一个想法,但是从 -Xmx2000M 更改为 -Xmx2500 在恒定的工作时间内没有任何意义。另外,我查看了“top”命令,在运行程序时,有一块空闲内存。
【解决方案3】:

Java 中的哈希表可能会在 GC 中触发令人讨厌的行为,尤其是当它们长期存在且很大时。 HashMap 也是如此。要确定您是否属于这种情况,请检查进程需要多少 CPU。如果它需要大量 CPU,则 GC 正在运行。如果它不需要任何 CPU(只是挂起),那么您就有了死锁。

要查找死锁的原因,请创建线程转储并对其进行分析。如果您使用的是 Eclipse,您可能需要查看 Lockness

【讨论】:

    【解决方案4】:

    我不太明白您自制的分析机制是如何工作的。但看起来它是在您正在检查的程序中完成的,并且在该程序中占用了大量内存。

    顺便说一句,您在该 HashMap 中使用了Vectors。向量是同步的,因此比ArrayLists 慢一些。你可能会从改变它中获得一点点性能。

    回到主要问题。其他分析工具采用不同的方法:它们不是构建结果的内存数据结构,而是将所有内容记录到文件中。之后,一旦原始程序运行,另一个程序读取、消化和分析日志文件。事实证明,与将仪器移植到程序中相比,写入缓冲文件在时间/内存使用方面更加一致且干扰更少。

    【讨论】:

      【解决方案5】:

      看起来很像死锁。尝试从Hashtable 切换到ConcurrentHashMap 或调查您的应用程序并添加额外的锁来解决死锁。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-07-21
        • 2012-03-27
        • 2013-10-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-23
        • 1970-01-01
        相关资源
        最近更新 更多