今天在对一个Hashtable对象进行 搜索 -> 删除 操作时遇到的一个问题,开始的使用我使用的是Hashtable的Iterator,然后直接执行:

Hashtable.remove(key); 抛出异常  java.util.ConcurrentModificationException

查了一下java api doc,相关介绍如下:

由迭代器返回的 Iterator 和由所有 Hashtable 的“collection 视图方法”返回的 Collection 的 listIterator 方法都是快速失败的:在创建 Iterator 之后,如果从结构上对 Hashtable 进行修改,除非通过 Iterator 自身的移除或添加方法,否则在任何时间以任何方式对其进行修改,Iterator 都将抛出 ConcurrentModificationException。因此,面对并发的修改,Iterator 很快就会完全失败,而不冒在将来某个不确定的时间发生任意不确定行为的风险。由 Hashtable 的键和值方法返回的 Enumeration不是快速失败的。

Hashtable<Integer,Integer> t = new Hashtable<Integer,Integer>();
     
     for(int i=0;i<10;i++)
     {
      t.put(i,i*10);
     }   
     
     System.out.println("t.size():" + t.size());
     System.out.println(t.get(6));
     
     System.out.println();       
         
        Iterator<Integer> i = t.keySet().iterator();
     
     while(i.hasNext())
     {
      int key = i.next();
      
      if(key == 3)      
      {
       //t.remove(key);  //这样删除,抛出异常 java.util.ConcurrentModificationException       
       i.remove(); //只有这样,才可以成功的删除一个元素
      }
     }
     
     System.out.println("t.size():" + t.size());     
     System.out.println(t.get(6));

使用上面这种t.keySet().iterator();方式,如果在多线程情况下,也是会抛出 java.util.ConcurrentModificationException

在多线程并发的情况下,在增加、修改、删除、遍历时全加上 synchronized :

public synchronized void delKey(int key)
 {  
  Iterator<Integer> i = t.keySet().iterator();
  while(i.hasNext())
     {
      int abc = i.next();
      
      //t.remove(key); //抛出异常 java.util.ConcurrentModificationException
   
      if(abc == key)
       i.remove(); //只有这样,才可以成功的删除一个元素
     }     
 }

当在多线路中调用 delKey()时,必须在定义delKey()方法前使用:synchronized,以保证多线程调用安全。

---------------------------------------------------------------------------------------------------------------------------------------------------------------------

其实还有一种更早的(更原始的)的安全方法,使用Enumeration,这种方式不管是在单线程还是在多线程中执行都是安全的(注意下面的特别说明):

Hashtable<Integer,Integer> t = new Hashtable<Integer,Integer>();
     
     for(int i=0;i<10;i++)
     {
      t.put(i,i*10);
     }    
     
     System.out.println("t.size():" + t.size());
     System.out.println(t.get(6));
     
     System.out.println();    
     
     Enumeration<Integer> e = t.keys();
     while(e.hasMoreElements())
     {
      int key = e.nextElement();
      
      if(key == 3)
      t.remove(key);
     } 
     
     System.out.println("t.size():" + t.size());     
     System.out.println(t.get(6));

特别注意:

虽然使用Enumeration来遍历元素是线程安全的,高并发的情况下进行增加、修改、遍历,也不会抛什么异常,但如果在遍历Enumeration的同时删除里面的一个元素虽不会抛出什么异常,但结果可能不是你想像的:list = new Vector<String>();
  
  list.add("1");
  list.add("2");
  list.add("3");
  list.add("4");
  list.add("5");
  list.add("6");
  
  Enumeration<String> i = list.elements();
  while(i.hasMoreElements())
  {
   String str = i.nextElement();
   
   System.out.println(str);
   
   list.removeElement(str); //在这里删除
  }

//输出结果:

1

3

5

我看到这个结果,我是真的很意外。

2011-04-18

Hashtable 删除元素, 抛出异常 java.util.ConcurrentModificationException的更多相关文章

  1. 遍历List过程中删除操作报java.util.ConcurrentModificationException错误

    1:遍历List 同时 remove 元素,出现java.util.ConcurrentModificationException错误 @Test public void test3(){ List& ...

  2. java foreach循环抛出异常java.util.ConcurrentModificationException

    代码如下: for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { if (Integer.parseInt(i ...

  3. list删除操作 java.util.ConcurrentModificationException

    首先大家先看一段代码: public static void main(String[] args) { List<String> listStr = new ArrayList<S ...

  4. 集合循环删除问题-报错java.util.ConcurrentModificationException解析

    java.util.ConcurrentModificationException 异常问题详解 环境:JDK 1.8.0_111 在Java开发过程中,使用iterator遍历集合的同时对集合进行修 ...

  5. java.util.ConcurrentModificationException 异常问题详解

    环境:JDK 1.8.0_111 在Java开发过程中,使用iterator遍历集合的同时对集合进行修改就会出现java.util.ConcurrentModificationException异常, ...

  6. 为什么阿里巴巴禁止在 foreach 循环里进行元素的 remove/add 操作--java.util.ConcurrentModificationException

    摘要 foreach循环(Foreach loop)是计算机编程语言中的一种控制流程语句,通常用来循环遍历数组或集合中的元素. 在阿里巴巴Java开发手册中,有这样一条规定: 但是手册中并没有给出具体 ...

  7. 再次踩bug:遍历删除list(java.util.ConcurrentModificationException)

    再次踩bug:遍历删除list(java.util.ConcurrentModificationException) 使用 List<Long> list = new ArrayList& ...

  8. JAVA循环迭代中删除或添加集合数据报java.util.ConcurrentModificationException错误

    1.写出下面的输出结果 public class test{ public static void main(String [] args) List<String> list = new ...

  9. java.util.ConcurrentModificationException 异常解决的方法及原理

    近期在修程序的bug,发现后台抛出下面异常: Exception in thread "main" java.util.ConcurrentModificationExceptio ...

随机推荐

  1. linux下监控某个目录是否被更改

    需求:对一个目录(比如/data/test)进行监控,当这个目录下文件或子目录出现变动(如修改.创建.删除.更名等操作)时,就发送邮件!针对上面的需求,编写shell脚本如下: [root@cento ...

  2. linux下向一个文件中的某行插入数据的做法

    sed -i 'ni\x' test.file        表示向test.file文件里的第n行的前面添加x内容sed -i 'na\x' test.file       表示向test.file ...

  3. Iptables防火墙规则使用梳理

    iptables是组成Linux平台下的包过滤防火墙,与大多数的Linux软件一样,这个包过滤防火墙是免费的,它可以代替昂贵的商业防火墙解决方案,完成封包过滤.封包重定向和网络地址转换(NAT)等功能 ...

  4. vue全局 关键字搜索 v-search

    一款基于 vuejs & weui 的全屏搜索组件:https://www.npmjs.com/package/vue-search

  5. 作业20171130 final发布 成绩

    申诉 对成绩有疑问或不同意见的同学,请在群里[@杨贵福]. 申诉时间截止2017年12月16日 17:00. 更新 第一周和第二周成绩分别应占比20%和10%,计算时刚好反了.所以同学们的最终成绩有变 ...

  6. #个人博客作业Week3——必应词典案例分析

    第一部分 调研以及评测 一.BUG分析   1. 翻译部分原文语言检测部分 1) 症状: 当选择原文语言是简体中文时,输入英文查询,程序不报错,继续翻译,选择其他类型语言也是如此. 且如果出现这种情况 ...

  7. linux内核分析第四次实验

    实验步骤: 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用.本次实验中我使用第20号系统调用getpid()函数,用于取得进程识别码. C代码(getpid.c): #include ...

  8. 【MOOC EXP】Linux内核分析实验七报告

    程涵  原创博客 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 可执行程序的装载 知识点梳理 一.预处 ...

  9. Linux内核分析(第九周)

    第一周总结1.存储程序计算机 + 函数调用堆栈 + 中断机制 2.堆栈:C语言程序运行时候必须的一个记录调用路径和参数的空间(函数调用框架/提供局部变量/传递参数/保存返回地址) 不同指令可能实现相同 ...

  10. Java计算器(结对)

    一:题目简介 我们要做的是一个多功能计算器,Java程序编辑器是:图形界面.线程.流与文件等技术的综合应用. 图形界面的实现:考虑到简单.实用.高效等特点,就选择了Swing来完成实现,在选择组件上, ...