在javadoc中找到这样一段话:
代码
- * <p>The iterators returned by all of this class's "collection view methods"
- * are <i>fail-fast</i>: if the map is structurally modified at any time after
- * the iterator is created, in any way except through the iterator's own
- * <tt>remove</tt> or <tt>add</tt> methods, the iterator will throw a
- * <tt>ConcurrentModificationException</tt>. Thus, in the face of concurrent
- * modification, the iterator fails quickly and cleanly, rather than risking
- * arbitrary, non-deterministic behavior at an undetermined time in the
- * future.
如果hashmap在迭代的同时,被其他线程修改,则会抛出一个ConcurrentModificationException异常,如以下这段程序:
代码
- package hashmap;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.Map;
- import java.util.Set;
- import java.util.Map.Entry;
- public class HashMapTest {
- private static final Map<Integer, Integer> map = new HashMap<Integer, Integer>();
- public static void main(String[] args) {
- try {
- for (int i = 0; i < 10; i++) {
- map.put(i, i);
- }
- new Thread() {
- @Override
- public void run() {
- Set<Entry<Integer, Integer>> set = map.entrySet();
- synchronized (map) {
- Iterator<Entry<Integer, Integer>> it = set.iterator();
- while (it.hasNext()) {
- Entry<Integer, Integer> en = it.next();
- System.out.println(en.getKey());
- }
- }
- }
- }.start();
- for (int i = 0; i < 10; i++) {
- map.put(i, i);
- }
- } catch (Throwable e) {
- e.printStackTrace();
- }
- }
- }
为了解决这个问题,jdk5.0以前的版本提供了Collections.SynchronizedXX();方法,对已有容器进行同步实现,这样容器在迭代时其他线程就不能同时进行修改了,但是由于Collections.SynchronizedXX()生成的容器把所有方法都进行了同步,其他线程如果只是读取数据也必须等待迭代结束。于是JDK5.0中新加了ConcurrentHashMap类,这个类通过内部独立锁的机制对写操作和读操作分别进行了同步,当一个线程在进行迭代操作时,其他线程也可以同步的读写,Iterator返回的只是某一时点上的,不会抛ConcurrentModificationException异常,比起hashmap效率也不会有太大损失