- 首先,关于 Hashtable的源码相关解析可以看 Java8源码-Hashtable(2)
HashMap为什么线程不安全
- 多线程 put 操作后, get 操作导致死循环,导致 cpu100%的现象。 主要是多线程同时put 时, 如果同时触发了 rehash 操作, 会导致扩容后的 HashMap 中的链表中出现循环节点, 进而使得后面 get 的时候, 会死循环。关于死循环具体形成,可见 HashMap的死循环(HashMap infinite loop)
- 多线程 put 操作, 导致元素丢失, 也是发生在多个线程对 hashmap 扩容时。
二者的区别与联系
- Hashtable和HashMap,从存储结构和实现来讲基本上都是相同的。它和HashMap的最大的不同是它是线程安全的(通过对put,remove等方法用synchronize关键字修饰),另外它不允许key和value为null。Hashtable是个过时的集合类,不建议在新代码中使用,不需要线程安全的场合可以用HashMap替换,需要线程安全的场合可以用ConcurrentHashMap替换。但这并不是我们不去了解它的理由。
- Hashtable是如何实现线程安全的的?
通过对put,remove等方法用synchronize关键字修饰,通过源码可以看到 - HashTable 的效率比较低的原因
在线程竞争激烈的情况下 HashTable 的效率非常低下。 因为当一个线程访问HashTable 的同步方法时, 访问其他同步方法的线程就可能会进入阻塞或者轮训状态。 如线程 1 使用 put 进行添加元素, 线程 2 不但不能使用 put 方法添加元素, 并且也不能使用get 方法来获取元素, 所以竞争越激烈效率越低 判断是否含有某个键问题
- 在 HashMap 中, null 可以作为键, 这样的键只有一个; 可以有一个或多个键所对应的值为 null。 当 get()方法返回 null 值时, 既可以表示 HashMap 中没有该键, 也可以表示该键所对应的值为 null。 因此, 在 HashMap 中不能用 get()方法来判断 HashMap 中是否存在某个键, 而应该用 containsKey()方法来判断。
- Hashtable 的键值都不能为 null, 所以可以用 get()方法来判断是否含有某个键。
Hashtable和HashMap的不同点?