java.util.Hashtable实现代码局部变量到元素表重新赋值

标签 java collections

我想知道为什么 java.util.Hashtable 方法通过本地分配的变量对元素数组进行操作,而不是直接访问类成员。它是否与同步有关(在方法调用之间保持元素数组处于一致状态?)

例如:Entry<?,?> tab[] = table;

 private void addEntry(int hash, K key, V value, int index) {
420         modCount++;
421 
422         Entry<?,?> tab[] = table;
423         if (count >= threshold) {
424             // Rehash the table if the threshold is exceeded
425             rehash();
426 
427             tab = table;
428             hash = key.hashCode();
429             index = (hash & 0x7FFFFFFF) % tab.length;
430         } 

或在

456     public synchronized V put(K key, V value) {
457         // Make sure the value is not null
458         if (value == null) {
459             throw new NullPointerException();
460         }
461 
462         // Makes sure the key is not already in the hashtable.
463         Entry<?,?> tab[] = table;
464         int hash = key.hashCode();
465         int index = (hash & 0x7FFFFFFF) % tab.length;
466         @SuppressWarnings("unchecked")
467         Entry<K,V> entry = (Entry<K,V>)tab[index];
468         for(; entry != null ; entry = entry.next) {
469             if ((entry.hash == hash) && entry.key.equals(key)) {
470                 V old = entry.value;
471                 entry.value = value;
472                 return old;
473             }
474         }
475 
476         addEntry(hash, key, value, index);
477         return null;
478     }

最佳答案

我觉得只留下评论很不好,这个问题应该得到一个正确的答案,所以这里是一个快速尝试rehash (ha) 这些评论。

  • Hashtable是同步的(所有公共(public)方法都是 synchronized ,或者返回一个同步集合( keySet()entrySet()values() )),这使得它成为 thread safe (某些规则和限制可能适用)
  • rehash()方法是 protected : 它可以从子类中调用。
  • 但它不是synchronized ,因此子类的实例可以调用 rehash()同时与另一个需要访问 table 的方法.
    因此,为了避免 table 上的竞争条件,这些方法保存了对数组引用的本地副本,然后可以安全地使用该本地数组:if rehash()被调用时,它将构建一个新数组,而不会干扰处理旧数组的其他线程。

JDK 1.0.2 的版本已经是这样了(找到它 here ,Windows .exe 是自解压的 zip 文件,所以 unzip 处理它,在那里你会找到 src.zip -- 有趣的是 Hashtable.java 内部有 3 个类,没有内部类,因为那些是在 1.1 中引入的)。

这种设计鼓励继承Hashtable从它的功能中获益,但组合应该受到青睐。我找到了一个 bug entry特定于 Hashtable 的子类(尽管与线程安全无关),其中 Josh Bloch 说:

This sort of problem can be avoided by using delegation rather than subclassing.

在评论中引用@pvg,以获得一个很好的总结:

A somewhat broader answer is that this is basically an early 90s design that has just had a long life and it shows. It's a class that tries to be both threadsafe and extensible through subclassing at the same time, something the class library avoids in later design iterations.

关于java.util.Hashtable实现代码局部变量到元素表重新赋值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45665101/

相关文章:

java - NavigableMap subMap/headMap/tailMap 是否有通用实现?

java - 使用 Eclipse 访问现有的 SQLite 数据库

python - 如何在没有引用对象实例的情况下获取集合名称?

java - 仅设置拦截器关闭端点

java - 增加 sqlworkbench/J 的堆大小

java - 我可以获得对 List<> 对象的引用(该对象引用其元素之一)吗?

java - 如何使用自然的 entrySet() 顺序迭代 HashMap?

.net - 可枚举的先决条件

java - 对于可序列化的父类(super class),如果我们序列化子类,为什么会调用 super 构造函数

java - 日历偏移问题