package com.test.io;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedList;

import com.mysql.jdbc.Buffer;

public class ReadKeyFile {
    public static void main(String[] args) throws IOException {

        BufferedReader bufferedReader=null;
        try {
            bufferedReader = new BufferedReader(new FileReader("C:/Users/Administrator/Desktop/test.txt"));
            LinkedList<String> list = new LinkedList<String>();
            String str=bufferedReader.readLine();
            while((str=bufferedReader.readLine())!=null) {
                System.out.println(str);
                list.add(str);
            }
            System.out.println("------------");
            for (String string : list) {
                System.out.println(list.removeLast());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(bufferedReader != null)
                bufferedReader.close();
        }
    }
}

结果及报错:

22222222222222222222
33333333333333333333
44444444444444444444
55555555555555555555
66666666666666666666
77777777777777777777
------------
77777777777777777777
java.util.ConcurrentModificationException
    at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:966)
    at java.util.LinkedList$ListItr.next(LinkedList.java:888)
    at com.test.io.ReadKeyFile.main(ReadKeyFile.java:24)

test.txt:

11111111111111111111
22222222222222222222
33333333333333333333
44444444444444444444
55555555555555555555
66666666666666666666
77777777777777777777

如果将源代码红色部分替换为以下,则可以正常输出,可见问题并不在remveLast()方法,而在迭代。

System.out.println(list.removeLast());
System.out.println(list.removeLast());

在网上查到一段文字:

1.在使用增强for循环进行集合的迭代的时候其实默认使用的是迭代器;2.因此在循环中不能使用集合的引用变量直接操作集合,避免导致多线程并发访问的安全性异常。

1的意思即增强for循环的遍历方式类似与:

Iterator<String> iterator = list.iterator();
            while(iterator.hasNext())
                System.out.println(iterator.next());

鉴于此,有必要看一下LinkedList的代码。在LinkedList中,这个iterator就是ListItr ,它是继承自Itr类,next()方法正是出自Itr类,在里面找到next()的源码如下:

public E next() {
            checkForComodification();
            try {
                int i = cursor;
                E next = get(i);
                lastRet = i;
                cursor = i + 1;
                return next;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
}

注意checkForComodification(),这就是报错的地方啦,具体是在下面这个地方报的错:

final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
}

根据我们的测试:LinkedList打印出第一排7就报错了。

modCount 这个在打应出第一排7之后的值应该为8,因为add了7次,又removeLast了一次嘛

那expectedModCount为多少呢?

看看Itr源代码吧,真乱,又实在是不想去读注释,我还是去翻翻JAVA编程思想先。

好吧,翻了一下书没翻到,百度了一下,又重新看了下代码,继续上面的问题,expectedModCount的值。

expectedModCount的值在removeLast之后为7。因为add里面有expectedModCount=modCount这样的语句,而removeLast里面没有。

这样的机制,应该是为了检测一边迭代,一边修改集合的危险操作。

LinkedList - java.util.ConcurrentModificationException的更多相关文章

  1. Iterator之java.util.ConcurrentModificationException

    在运行以下代码时,会报java.util.ConcurrentModificationException异常, public class Demo { public static void main( ...

  2. 增强for循环 java.util.ConcurrentModificationException

    Java中的Iterator功能比较简单,并且只能单向移动: (1) 使用方法iterator()要求容器返回一个Iterator.第一次调用Iterator的next()方法时,它返回序列的第一个元 ...

  3. java.util.ConcurrentModificationException 解决办法(转载)

    今天在项目的中有一个需求,需要在一个Set类型的集合中删除满足条件的对象,这时想当然地想到直接调用Set的remove(Object o)方法将指定的对象删除即可,测试代码:   public cla ...

  4. java.util.ConcurrentModificationException --map

    key:3-key key:/v1.02-key Exception in thread "main" java.util.ConcurrentModificationExcept ...

  5. 偶遇到 java.util.ConcurrentModificationException 的异常

    今天在调试程序 遇到了如此问题 贴上代码来看看稍后分析 List<String> list = null;boolean isUpdate = false;try { list = JSO ...

  6. 对ArrayList操作时报错java.util.ConcurrentModificationException null

    用iterator遍历集合时要注意的地方:不可以对iterator相关的地方做添加或删除操作.否则会报java.util.ConcurrentModificationException 例如如下代码: ...

  7. java.util.ConcurrentModificationException 解决办法

    在使用iterator.hasNext()操作迭代器的时候,如果此时迭代的对象发生改变,比如插入了新数据,或者有数据被删除. 则使用会报以下异常:Java.util.ConcurrentModific ...

  8. java.util.ConcurrentModificationException 解决办法(转)

    今天在项目的中有一个需求,需要在一个Set类型的集合中删除满足条件的对象,这时想当然地想到直接调用Set的remove(Object o)方法将指定的对象删除即可,测试代码:   public cla ...

  9. java集合--java.util.ConcurrentModificationException异常

    ConcurrentModificationException 异常:并发修改异常,当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常.一个线程对collection集合迭代,另一个线程对Co ...

随机推荐

  1. c_水程序

    * ** This program reads input lines from the standard input and prints ** each input line, followed ...

  2. COGS 2416.[HZOI 2016]公路修建 & COGS 2419.[HZOI 2016]公路修建2 题解

    大意: [HZOI 2016]公路修建 给定一个有n个点和m-1组边的无向连通图,其中每组边都包含一条一级边和一条二级边(连接的顶点相同),同一组边中的一级边权值一定大于等于二级边,另外给出一个数k( ...

  3. 如何查看Git对象

    原文:http://gitbook.liuhui998.com/7_2.html 如果在阅读本文之前,你还不知道git是如何进行存储的,请先阅读<Git是如何存储对象的>. 我们可以使用c ...

  4. (转)高性能网站架构之缓存篇—Redis集群增删节点

    标签: 高性能架构集群缓存redis 上一篇文章,我们搭建了Redis-cluster集群,这篇博客跟大家讲一下如何在一个运行的集群上增加节点或者删除节点. Redis集群添加节点 首先我们要新建立一 ...

  5. android一句话搞定图片加载

    http://square.github.io/picasso/ Picasso.with(context).load("http://i.imgur.com/DvpvklR.png&quo ...

  6. cxGRID中的字段怎么能以0.00的格式显示

    CXGRID中的字段如何能以0.00的格式显示在CXGRID中如何让字段能以0.00的格式显示,我的字段是FLOAT类型,满意的马上给分! ------解决方案-------------------- ...

  7. Tcpdump的详细用法

    1. TCPDump介绍 TcpDump可以将网络中传送的数据包的"头"完全截获下来提供分析.它支持针对网络层.协议.主机.网络或端口的过滤,并提供and.or.not等逻辑语句来 ...

  8. uva 489.Hangman Judge 解题报告

    题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...

  9. WCF重写ServiceHost,实现独立配置文件

    有时我们需要将WCF的配置文件放在单独的配置文件中,而默认情况下WCF又是在web.config或app.config中去寻找服务配置.如果我们把配置文件放在另一个config文件中,如何让WCF知道 ...

  10. phpexcel生成excel并下载

    Loader::import('PHPExcel.Classes.PHPExcel'); // tp5中只需将phpexcel文件放入extend文件夹中,即可采用该方法引入,需要先 use thin ...