Java Hashtable put 方法减慢了我的应用程序

Posted

技术标签:

【中文标题】Java Hashtable put 方法减慢了我的应用程序【英文标题】:Java Hashtable put method slow down my application 【发布时间】:2012-01-15 14:28:37 【问题描述】:

我需要做的:

Dictionary cache;
cache = new Hashtable();
this.getDocument().putProperty("imageCache", cache);

然后我有一个方法:

cache.put(url, picture);

其中图片是一个图像对象。 我是这样创建的:

public Image getSmiley(String smileyName) 
    BufferedImage img = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
    Graphics g = img.getGraphics();
    ImageIcon myicon = new ImageIcon(getClass().getResource("/ola/smileys/" + smileyName + ".png"));
    myicon.paintIcon(null, g, 0, 0);
    return img;

我已经运行了一个分析,我发现当我调用这个方法“put”时,应用程序的速度非常慢。可能是什么原因?

非常感谢。

最好的问候

【问题讨论】:

什么是url?一个字符串? @Thilo - 我猜是URL ...看我的回答:-) 如何进行分析?也许您可以在调试模式下运行并继续进入put 方法之后,并确定哪个进程实际上减慢了应用程序 【参考方案1】:

我怀疑这可能是由于您使用 URL 类作为键类型。

URL.equals(Object) 的 javadoc 是这样说的:

如果两个 URL 对象具有相同的协议、引用等效的主机、在主机上具有相同的端口号、以及相同的文件和文件的片段,则它们是相等的。

如果两个主机名都可以解析为相同的 IP 地址,则认为两个主机是等效的;否则,如果任一主机名都无法解析,则主机名必须相等,不考虑大小写;或两个主机名都等于​​ null。

由于主机比较需要名称解析,因此该操作是阻塞操作。

当您使用 URL 实例作为映射中的键时,每次将键与不同的键进行比较时,您可能会触发 DNS 查找...这可能需要很长时间。


如果这是您的问题,那么您需要将映射的键类型更改为 StringURI ... 或其他没有昂贵的 equals(Object) 方法的东西。

【讨论】:

它会先尝试hashcode(),它被缓存在URL类中。所以我不认为它会导致应用程序慢得令人难以置信。然而,这真的取决于“难以置信”的慢。 是的...但是如果您假设您手中的URL 实例之前没有经过哈希处理,那么hashcode() 调用将需要解析主机名。另外,如果存在哈希冲突,则需要调用equals() ......对于当前表大小。 我同意你的看法。我遇到的第一个嫌疑人也是键类的hashcode()equals() 方法。但我真的怀疑 hashcode()equals() 是否会“令人难以置信地”减慢应用程序的速度。 这取决于主机的 DNS 查找速度。根据我的经验,它可以慢到足以被称为“令人难以置信的”减速。 你是对的。 handler.equals(this, u2) 将被调用,它会非常慢。【参考方案2】:

我只是猜测,但我认为这可能是由于必须调整底层哈希结构的大小。

当您将一个值“放入”哈希表时,一旦它达到一定的容量,它就必须扩展底层数组——否则,您最终会遇到很多哈希冲突。然而,这种数组扩展操作代价高昂——它必须为新数组分配空间并将值复制到新数组中。

一个建议是给 Hashtable 构造函数一个合理的初始容量。

【讨论】:

+1 不过也不算贵。当然,OP 并没有量化“难以置信”。【参考方案3】:

“难以置信”是多少?

我无法保证它会带来多少改进,但请尝试使用HashMap 而不是HashtableHashMap 不同步,我猜你在这里不需要,因为无论如何都应该在一个线程上为你的 UI 完成。

请参阅Differences between HashMap and Hashtable? 了解有关它们之间差异的更多详细信息。

【讨论】:

这是一个中肯的建议,但不应使任何明显的性能有所不同,更不用说“令人难以置信”的东西了。 Thilo - 同意。 +1 尼克关于为地图提供初始容量的回答。【参考方案4】:

我假设您正在尝试预加载缓存,以便您可以执行一些操作,例如在 JEditorPane 中显示本地图像。

我刚刚遇到了这个问题,Stephen C 正确地发现了这个问题。

原来我用的是 http:// 开头的 url,我切换到了 file:/ 开头的 url,它解决了这个问题。

这些 url 从未真正连接到,它们只是散列的唯一键,因此只需确保 URL 对象知道它不需要 DNS 查找来解析它们就足够了,并且更改为文件协议就可以了.

【讨论】:

以上是关于Java Hashtable put 方法减慢了我的应用程序的主要内容,如果未能解决你的问题,请参考以下文章

HashMap和HashTable的区别

Java:ConcurrentHashMap

JsonParser 的 Parse 方法大大减慢了我的代码

Java_深度剖析ConcurrentHashMap

集合之HashTable

java读写properties配置文件方法