Java学习笔记(4)
ConcurrentModificationException异常
- 何时会出现ConcurrentModificationException异常?
- ——对Vector,ArrayList在迭代的时候如果同时对其进行修改就会抛出java.util.ConcurrentModificationException异常
- ArrayList的iterator()方法的具体实现(在ArrayList的父类AbstractList中):
- public Iterator<E> iterator() {
- return new Iter();
- }
- Itr的具体实现(还是在AbstractList类中,Itr是AbstractList的一个成员内部类):
- private class Itr implements Iterator<E> {
- int cursor = 0;
- int lastRet = -1;
- int expectedModCount = modCount;
- public boolean hasNext() {
- return cursor != size();
- }
- public E next() {
- checkForComodification();
- try{
- E next = get(cursor);
- lastRet = cursor++;
- return next;
- } catch (IndexOutOdBoundsException) {
- checkForComodification();
- throw new NoSuchElementException();
- }
- }
- public void remove() {
if (lastRet == -1) - throw new IllegalStateException();
- checkForComodification();
- try {
- AbstractList.this.remove(lastRet);
- if (lastRet < cursor)
- cursor——;
- lastRet = -1;
- exceptionModCount = modCount;
- } catch (IndexOutOfBoundsException e) {
- throw new ConcurrentModificationException();
- }
- }
- final void checkForComodification() {
if (modCount != exceptionModCount) - throw new ConcurrentModificationException();
- }
- }
- cursor: 表示下一个要访问的元素的索引
- lastRet:表示上一个访问元素的索引
- exceptionModCount:表示对ArrayList修改次数的期望值,它的初始值为modCount
- modCount是AbstractList类中的一个成员变量,表示对List的修改次数,ArrayList每次调用自己的add()方法和remove()方法就会对modCount进行加一操作
- ArrayList中的remove()方法:
- public boolean remove(Object o) {
- if (o == null) {
- for (int index = 0; index < size; index++)
- if (elementData[index] == null) {
- fastRemove(index);
- return true;
- }
- } else {
- for (int index = 0; index < size; index++)
- if (o.equals(elementData[index])) {
- fastRemove(index);
- return true;
- }
- }
- return false;
- }
- private void fastRemove(int index) {
- modCount++;
- int numMoved = size - index - 1;
- if (numMoved > 0)
- System.arraycopy(elementData, index+1, elementData, index,
- numMoved);
- elementData[--size] = null; // Let gc do its work
- }
- 通过remove()方法删除元素最终是调用类fastRemove()方法,在fastRemove()方法中,首先对modCount进行加一操作,接下来就是删除元素操作,最后讲size进行减一操作,并将引用置为null以方便垃圾回收器进行回收工作
- 如何解决多线程中的该异常:
- 1)在使用iterator迭代的时候使用synchronized或者Lock进行同步
- 2)使用并发容器CopyOnWriteArrayList代替Vector