线程不安全的HashMap
多线程环境下,使用HashMap进行put操作会引起死循环,导致CPU利用率接近100%,是因为多线程会导致HashMap的Entry链表形成环形数据结构,一旦形成环形数据结构,Entry的next的节点永远不为空,就会产生死循环的Entry。
package com.genge.multithread;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
/**
* Created by Genge on 2016-06-10.
*/
public class UnsafeHashMap {
public static void main(String[] args) throws InterruptedException {
final HashMap<String, String> map = new HashMap<String, String>(2);
Thread t = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10000; i++) {
new Thread(new Runnable() {
public void run() {
map.put(UUID.randomUUID().toString(), "");
}
}, "ftf" + i).start();
}
}
}, "ftf");
t.start();
t.join();
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
}
38ef09e7-0bd8-4554-a9f6-1b28422b87e6 =
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode(HashMap.java:1429)
at java.util.HashMap$EntryIterator.next(HashMap.java:1463)
at java.util.HashMap$EntryIterator.next(HashMap.java:1461)
at com.genge.multithread.UnsafeHashMap.main(UnsafeHashMap.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Process finished with exit code 1
线程安全的HashTable
效率低下
因为当一个线程访问HashTable的同步方法的时候,其他线程也访问同步方法的时候就会进入阻塞或者轮询状态,因为都是使用
synchronized
获取的是this
对象锁,导致效率低下。
ConcurrentHashMap 效率高
首先将数据分成一段一段地存储,然后给每一个数据分配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问