1、 HashMap、HashTable、ConcurrentHashMap对比
线程不安全的HashMap
HashMap是线程不安全的,在多线程环境下,使用HashMap进行put操作会引起死循环,导致CPU使用率接近100%。
以下是一段会死循环的代码示例:
public static void main(String[] args) throws InterruptedException {
final HashMap<String, String> map = new HashMap<String, String>(2);
Thread t = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100000000; i++) {
new Thread(new Runnable() {
@Override
public void run() {
map.put(UUID.randomUUID().toString(), "");
}
}, "ftf" + i).start();
}
}
}, "ftf");
t.start();
t.join();
}
书中设置的循环次数为10000。可能我的笔记本内存太大(16G)跑起来绰绰有余,一会儿就执行完了。于是乎我把循环次数调大到100000000。笔记本的电风扇顺利的转了起来,看了一下CPU的负载到了很高,如下图:
进程监控
HashMap在并发执行put操作时会引起死循环,是因为多线程会导致HashMap的Entry链表形成环形数据结构,一旦形成环形数据结构,Entry的next节点永远不为空,就会产生死循环获取Entry。
效率低下的HashTable
为什么效率低下呢?因为使用了synchronized关键字来保证线程安全。所有访问HashTable的线程都竞争同一把锁。但是在线程竞争激烈的情况下,一个线程要访问HashTable的同步方法,其他线程也想访问时就进入了轮询状态。这样在线程竞争非常激烈时,效率就越低。
图片来源:https://www.cnblogs.com/chengxiao/p/6842045.html
ConcurrentHashMap的锁分段技术
HashTable效率低是因为所有线程都用一把锁。而ConcurrentHashMap先将数据分一段一段进行存储,然后给每一段分配一把锁,当一个线程占用锁访问其中一个段的数据时,其他的段的数据也能被其他线程访问。
图片来源:https://www.cnblogs.com/chengxiao/p/6842045.html
2. ConcurrentHashMap的结构
(未完待续)
网友评论