ConcurrentModificationException主要原因及处理方法

工作中碰到个ConcurrentModificationException,
/**
* 统计某一个磁盘的相关文件数据
* @author 浪子
*/
public class CountFile extends Thread{
//构造器,传入一个根目录名
public CountFile(String root){
this.rootDirName=root;
}
/**查看线程是否己执行完毕*/
public boolean isFinished(){
return finished;
}

//线程进行计算
public void run(){
long start=System.currentTimeMillis();
//计算目录下文件的总长度
lengthCount=countProcess(this.rootDirName);
long timeCost=System.currentTimeMillis()-start;
finished=true;
}

/**
* 计算一个目录下面文件相关数据
* @param dir:要计算的目录的名字
* @return:文件的总长度
*/
private int countProcess(String dir){
}
private boolean finished=false; /**是否己运行结束*/
}


/**
* 监视线程通讯模型
* 1.启动任务线程
* 2.对任务线程进行监视,
* @author 蓝杰
*/
public class MainCount implements Runnable{

public static void main(String[] args) {
java.io.File[] dirF=java.io.File.listRoots();//取得系统的根目录个数
//根据根目录个数创建统计线程对象并启动
for(int i=0;i<dirF.length;i++){
CountFile cf=new CountFile(dirF[i].getAbsolutePath());
cf.start();//这个线程主要对countList中的对象进行操作
countList.add(cf); //将每个统计线程对象放入要监视的集合中
}
System.out.println(dirF.length+"个统计线程对象己启动. . .");
//启动监视线程
new Thread(new MainCount()).start();
System.out.println("监视线程己启动. . .");
}

/**监视线程每隔3秒种检测统计线程集合,看是否有完成统计的
如有完成,则提取结果,将其从集合中移除**/
public void run(){
boolean flag=true;
String result="";
while(flag){
//每隔一秒钟,检查一下队列中的线程对象的状态
java.util.Iterator<CountFile> it=countList.iterator();
while(it.hasNext()){
[color=red]CountFile cf=it.next();[/color]
if(cf.isFinished()){//如果这个线程己统计完成
result+=cf.getResult();//取得统计结果
countList.remove(cf); //线程己运行完毕,可以移除了
}
}
//当统计线程对象队列为空时,说明所有任务己执行完毕,本监视线程也应退出了
if(countList.isEmpty()){
flag=false;
}
try{
Thread.sleep(3000);
}catch(Exception ef){}
}
System.out.println("并行统计结果如下: ");
System.out.println(result);
}
/**保存统计线程对象的队列*/
private static java.util.List<CountFile> countList=new java.util.ArrayList();
}

Exception in thread "Thread-3" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at ListenThread.MainCount.run(MainCount.java:53)
at java.lang.Thread.run(Thread.java:619)
上面话的意思是:

原因是因为:在LIst,Map或者Collection的时候,不要用它们的API直接修改集合的内容。对 List,Collection 或 Map 进行迭代操作过
程中尝试直接修改 Collection / Map 的内容时,即使是在单线程下运行,
java.util.ConcurrentModificationException 异常也将被抛出。


Iterator 是工作在一个独立的线程中。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化
时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以 Iterator 会马上抛出
java.util.ConcurrentModificationException 异常。


所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但可以使用 Iterator 本身的方法 remove() 来删除对
象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。

修改后的解决方法

public void run(){
boolean flag=true;
String result="";
[color=red] while(flag){
//每隔一秒钟,检查一下队列中的线程对象的状态
for(int i=0;i<countList.size();i++){
CountFile cf=countList.get(i);
if(cf.isFinished()){//如果这个线程己统计完成
result+=cf.getResult();//取得统计结果
countList.remove(cf); //线程己运行完毕,可以移除了
}
}[/color]
}
//当统计线程对象队列为空时,说明所有任务己执行完毕,本监视线程也应退出了
if(countList.isEmpty()){
flag=false;
}
try{
Thread.sleep(3000);
}catch(Exception ef){}
}
System.out.println("并行统计结果如下: ");
System.out.println(result);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值