学习自:
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
让索引自增用来继续向后遍历。