学习自:
http://www.cnblogs.com/skywang12345/p/3308762.html
java的集合里有一个叫做fail-fast机制。不论是HashMap,Hashtable,HashSet以及ArrayList等都实现了该机制。而且它们的实现方法都大同小异,主要是通过modCount与expectedModCount这两个变量值是否相等来判断的。而且它们都是是通过iterator迭代器来实现的,Hashtable内部的迭代器同时实现了Enumeration接口。
文章开头链接讲的很好,以ArrayList为例进行了fail-fast机制演练以及解决方法。这里,我以链接的博客为主记录下一些重要理解点。
知识点
1.fail-fast 机制是java集合中的一种错误机制。当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件。如果抛出异常java.util.ConcurrentModificationException!即,产生fail-fast事件!
2.若在多线程环境下使用fail-fast机制的集合,建议使用java.util.concurrent包下的类去取代java.util包下的类。
3.阅读源码可以得知,fail-fast机制主要依据modCount与expectedModCount是否相等来进行判断。(modCount来自于AbstractList)
modCount是该集合被修改的次数。在迭代器里进行这样的判断主要依据是:
如果只有一个线程在访问操作集合,那么该集合进行迭代遍历时,不会有什么问题。但是当有第二个甚至更多的线程也在访问操作该集合时,由于其他线程对集合进行了增删改,那么modCount值肯定会修改,不过由于expectedModCount是迭代器内部定义的变量,所以该值只等于使用iterator()时集合的modCount。那么当线程1开始迭代遍历集合,而线程2却在修改集合,那么线程1遍历集合时内部的expectedModCount与集合的modCount不相等,就会抛出java.util.ConcurrentModificationException异常。
4.ArrayList内部有一个Itr类,它提供了hasNext(),next()以及remove()等方法。在对集合进行iterator()遍历时非常有用。
hasNext()很简单,cursor用来当做索引且从0开始,遍历时不断自增并和集合内数据长度进行对比。
next()方法在名字上容易给人误解,以为当前得到的是下一个元素,其实不是的。看看源码:
仔细阅读next()不难发现,i其实就是索引,最终返回的elementData[lastRet = i]其实就是当前索引的值,当然,cursor = i + 1让索引自增用来继续向后遍历。
