Hashtable 删除元素, 抛出异常 java.util.ConcurrentModificationException
今天在对一个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的更多相关文章
- 遍历List过程中删除操作报java.util.ConcurrentModificationException错误
1:遍历List 同时 remove 元素,出现java.util.ConcurrentModificationException错误 @Test public void test3(){ List& ...
- java foreach循环抛出异常java.util.ConcurrentModificationException
代码如下: for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { if (Integer.parseInt(i ...
- list删除操作 java.util.ConcurrentModificationException
首先大家先看一段代码: public static void main(String[] args) { List<String> listStr = new ArrayList<S ...
- 集合循环删除问题-报错java.util.ConcurrentModificationException解析
java.util.ConcurrentModificationException 异常问题详解 环境:JDK 1.8.0_111 在Java开发过程中,使用iterator遍历集合的同时对集合进行修 ...
- java.util.ConcurrentModificationException 异常问题详解
环境:JDK 1.8.0_111 在Java开发过程中,使用iterator遍历集合的同时对集合进行修改就会出现java.util.ConcurrentModificationException异常, ...
- 为什么阿里巴巴禁止在 foreach 循环里进行元素的 remove/add 操作--java.util.ConcurrentModificationException
摘要 foreach循环(Foreach loop)是计算机编程语言中的一种控制流程语句,通常用来循环遍历数组或集合中的元素. 在阿里巴巴Java开发手册中,有这样一条规定: 但是手册中并没有给出具体 ...
- 再次踩bug:遍历删除list(java.util.ConcurrentModificationException)
再次踩bug:遍历删除list(java.util.ConcurrentModificationException) 使用 List<Long> list = new ArrayList& ...
- JAVA循环迭代中删除或添加集合数据报java.util.ConcurrentModificationException错误
1.写出下面的输出结果 public class test{ public static void main(String [] args) List<String> list = new ...
- java.util.ConcurrentModificationException 异常解决的方法及原理
近期在修程序的bug,发现后台抛出下面异常: Exception in thread "main" java.util.ConcurrentModificationExceptio ...
随机推荐
- windows平台下编辑的内容传到linux平台出现中文乱码的解决办法
现象说明:在windows下编辑的内容,上传到linux平台下出现中文乱码.如下: 在windows平台编写haha.txt文件,内容如下: 上传到linux平台,出现中文乱码,如下: 基本上面出现的 ...
- LDAP学习笔记总结
一.LDAP概念LDAP是轻量目录访问协议,英文全称是Lightweight Directory Access Protocol,一般都简称为LDAP.它是基于X.500标准的,但是简单多了并且可以根 ...
- C_运算符_逻辑表达式
// 除法取余运算符的例子 //2018年9月19日22:44:21 # include<stdio.h> int main(void) { printf(%, %-, -%, -%-, ...
- 【个人阅读】M1/M2阶段总结
1.以前博客的链接 http://www.cnblogs.com/zyctsl/p/4028006.html http://www.cnblogs.com/zyctsl/p/4094011.html ...
- Linux内核第三节 20135332武西垚
总结部分: Linux内核源代码: Arch 支持不同cpu的源代码:主要关注x86 Init 内核启动的相关代码:主要关注main.c,整个Linux内核启动代码start_kernel函数 K ...
- jeecg的下拉列表
jeecg里面下拉列表的使用 ①建立数据字典seo_id <t:dictSelect field="operationPromotionAccount" typeGroupC ...
- is interest important?
学习是不是一定要看兴趣呢?高中时觉得只要肯学即使不喜欢又能如何,大学之后被深深打脸,面对一周那么多的实习和报告,我悄悄告诉自己不是这块料 有一些事情我就是学不会.我却很容易相信一个人. 因此,无论我如 ...
- A Survey of Machine Learning Techniques Applied to Software Defined Networking (SDN): Research Issues and Challenges
将机器学习用到SDN中的综述:研究的问题和挑战 从流量分类.路由优化.服务质量(Qos)/体验质量(QoE)预测.资源管理和安全性的角度,回顾了机器学习算法如何应用于SDN领域. 相关知识 在SDN中 ...
- PHP使用MySQL实现消息队列
消息队列常用在流量削峰(秒杀场景),异步通信等地方. 大体的结构如下: 类似于消费者和生产者的关系,首先生产者在消息队列未满的时候,才将生产的产品放进消息队列中:消费者在消息队列不为空的时候,才从消息 ...
- HDU 2012 素数判定
http://acm.hdu.edu.cn/showproblem.php?pid=2012 Problem Description 对于表达式n^2+n+41,当n在(x,y)范围内取整数值时(包括 ...