- 浏览: 149956 次
- 性别:
- 来自: 北京
-
文章分类
最新评论
-
august_000:
很有道理,我已经亲自测试过了:
public class ...
单例模式之线程安全解析 -
Chris_bing:
一个单例有这么多名堂,最后那个内部类的解决方案很有创意啊,受教 ...
单例模式之线程安全解析
原文地址:http://www.cnblogs.com/sunwufan/archive/2012/05/21/2511747.html
当考虑到列表中需要修改的元素很多时,可以考虑上一篇博文:
通过CopyOnWriteArrayList,在遍历过程中,对list元素进行删除和添加操作
方法一(效率不高):
这个问题是说,你不能在对一个List进行遍历的时候将其中的元素删除掉 解决办法是,你可以先将要删除的元素用另一个list装起来,等遍历结束再remove掉 可以这样写
List delList = new ArrayList();//用来装需要删除的元素
for(Information ia:list)
if(ia.getId()==k){
n++;
delList.add(ia);
}
list.removeAll(delList);//遍历完成后执行删除
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
方法二:同步操作list时,一边迭代remove,一边新增.那么会报错 java.util.ConcurrentModificationException
查看api发现vector有个好方法可以解决这个错误.
首先是用arraylist
// private Vector list;//两种list方式
private List list;
public void init(){
// list = new Vector();
list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.add("f");
}
public void removeIt(){//iterator
Iterator it = list.iterator();
for(int i=0;it.hasNext();i++){
String a = (String)it.next();
System.out.println(a);
if(a.equals("c")){
//list.remove(a);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
it.remove();
System.out.println("remove c");
}
}
}
// public void removeEm(){//enumeration
// Enumeration e = list.elements();
// for(int i=0;e.hasMoreElements();i++){
// String a = (String)e.nextElement();
// System.out.println(a);
// if(a.equals("c")){
// try {
// Thread.sleep(1000);
// } catch (InterruptedException ee) {
// }
// list.remove(a);
// System.out.println("remove c");
// }
// }
// }
public void add(){//先用迭代,再添加
try {
Thread.sleep(500);
} catch (Exception e) {
// TODO: handle exception
}
list.add("c");
System.out.println("add c");
}
public void run() {
removeIt();
// removeEm();
}
public static void main(String[] args) {
TestConcurrentModificationException t = new TestConcurrentModificationException();
t.init();
t.start();
t.add();
}
运行结果:
a
b
c
add c
Exception in thread "Thread-0" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.remove(Unknown Source)
at test.TestConcurrentModificationException.removeIt(TestConcurrentModificationException.java:33)
at test.TestConcurrentModificationException.run(TestConcurrentModificationException.java:69)
其次是vector
private Vector list;//两种list方式
// private List list;
public void init(){
list = new Vector();
// list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.add("f");
}
public void removeIt(){//iterator
Iterator it = list.iterator();
for(int i=0;it.hasNext();i++){
String a = (String)it.next();
System.out.println(a);
if(a.equals("c")){
//list.remove(a);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
it.remove();
System.out.println("remove c");
}
}
}
public void removeEm(){//enumeration
Enumeration e = list.elements();
for(int i=0;e.hasMoreElements();i++){
String a = (String)e.nextElement();
System.out.println(a);
if(a.equals("c")){
try {
Thread.sleep(1000);
} catch (InterruptedException ee) {
}
list.remove(a);
System.out.println("remove c");
}
}
}
public void add(){//先用迭代,再添加
try {
Thread.sleep(500);
} catch (Exception e) {
// TODO: handle exception
}
list.add("c");
System.out.println("add c");
}
public void run() {
// removeIt();
removeEm();
}
public static void main(String[] args) {
TestConcurrentModificationException t = new TestConcurrentModificationException();
t.init();
t.start();
t.add();
}
运行结果:
a
b
c
add c
remove c
e
f
c
remove c
api上说,
由 Vector 的 iterator 和 listIterator 方法所返回的迭代器是快速失败的:如果在迭代器创建后的任意时间从结构上修改了向量(通过迭代 器自身的 remove 或 add 方法之外的任何其他方式),则迭代器将抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就完全失败,而不是冒着在将来不确定的时间任意发生 不确定行为的风险。Vector 的 elements 方法返回的 Enumeration 不是 快速失败的。
注意,迭代器的快速失败行为不能得到保证,一般来说,存在不同步的并发修改时,不可能作出任何坚决的保证。快速失败迭代器尽最大努力抛出 ConcurrentModificationException。因此,编写依赖于此异常的程序的方式是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测 bug。
当然如果使用其他的集合,那就没有什么好办法了.只有存放起来,每次取一个list对象,并不是实时.
当考虑到列表中需要修改的元素很多时,可以考虑上一篇博文:
通过CopyOnWriteArrayList,在遍历过程中,对list元素进行删除和添加操作
方法一(效率不高):
这个问题是说,你不能在对一个List进行遍历的时候将其中的元素删除掉 解决办法是,你可以先将要删除的元素用另一个list装起来,等遍历结束再remove掉 可以这样写
List delList = new ArrayList();//用来装需要删除的元素
for(Information ia:list)
if(ia.getId()==k){
n++;
delList.add(ia);
}
list.removeAll(delList);//遍历完成后执行删除
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
方法二:同步操作list时,一边迭代remove,一边新增.那么会报错 java.util.ConcurrentModificationException
查看api发现vector有个好方法可以解决这个错误.
首先是用arraylist
// private Vector list;//两种list方式
private List list;
public void init(){
// list = new Vector();
list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.add("f");
}
public void removeIt(){//iterator
Iterator it = list.iterator();
for(int i=0;it.hasNext();i++){
String a = (String)it.next();
System.out.println(a);
if(a.equals("c")){
//list.remove(a);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
it.remove();
System.out.println("remove c");
}
}
}
// public void removeEm(){//enumeration
// Enumeration e = list.elements();
// for(int i=0;e.hasMoreElements();i++){
// String a = (String)e.nextElement();
// System.out.println(a);
// if(a.equals("c")){
// try {
// Thread.sleep(1000);
// } catch (InterruptedException ee) {
// }
// list.remove(a);
// System.out.println("remove c");
// }
// }
// }
public void add(){//先用迭代,再添加
try {
Thread.sleep(500);
} catch (Exception e) {
// TODO: handle exception
}
list.add("c");
System.out.println("add c");
}
public void run() {
removeIt();
// removeEm();
}
public static void main(String[] args) {
TestConcurrentModificationException t = new TestConcurrentModificationException();
t.init();
t.start();
t.add();
}
运行结果:
a
b
c
add c
Exception in thread "Thread-0" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.remove(Unknown Source)
at test.TestConcurrentModificationException.removeIt(TestConcurrentModificationException.java:33)
at test.TestConcurrentModificationException.run(TestConcurrentModificationException.java:69)
其次是vector
private Vector list;//两种list方式
// private List list;
public void init(){
list = new Vector();
// list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.add("f");
}
public void removeIt(){//iterator
Iterator it = list.iterator();
for(int i=0;it.hasNext();i++){
String a = (String)it.next();
System.out.println(a);
if(a.equals("c")){
//list.remove(a);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
it.remove();
System.out.println("remove c");
}
}
}
public void removeEm(){//enumeration
Enumeration e = list.elements();
for(int i=0;e.hasMoreElements();i++){
String a = (String)e.nextElement();
System.out.println(a);
if(a.equals("c")){
try {
Thread.sleep(1000);
} catch (InterruptedException ee) {
}
list.remove(a);
System.out.println("remove c");
}
}
}
public void add(){//先用迭代,再添加
try {
Thread.sleep(500);
} catch (Exception e) {
// TODO: handle exception
}
list.add("c");
System.out.println("add c");
}
public void run() {
// removeIt();
removeEm();
}
public static void main(String[] args) {
TestConcurrentModificationException t = new TestConcurrentModificationException();
t.init();
t.start();
t.add();
}
运行结果:
a
b
c
add c
remove c
e
f
c
remove c
api上说,
由 Vector 的 iterator 和 listIterator 方法所返回的迭代器是快速失败的:如果在迭代器创建后的任意时间从结构上修改了向量(通过迭代 器自身的 remove 或 add 方法之外的任何其他方式),则迭代器将抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就完全失败,而不是冒着在将来不确定的时间任意发生 不确定行为的风险。Vector 的 elements 方法返回的 Enumeration 不是 快速失败的。
注意,迭代器的快速失败行为不能得到保证,一般来说,存在不同步的并发修改时,不可能作出任何坚决的保证。快速失败迭代器尽最大努力抛出 ConcurrentModificationException。因此,编写依赖于此异常的程序的方式是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测 bug。
当然如果使用其他的集合,那就没有什么好办法了.只有存放起来,每次取一个list对象,并不是实时.
发表评论
-
(转)Spring声明式事务配置详解
2013-11-11 16:45 1857Spring声明式事务功能应该是大家应用Spring中使用的最 ... -
(转)Java几款性能分析工具的对比
2013-11-01 14:26 1059来源:http://www.javaweb.cc/langua ... -
HashMap的遍历
2013-11-01 14:15 9261、新建一个HashMap Map<Integer , ... -
java将汉子转换成汉语拼音
2013-11-01 13:51 951import net.sourceforge.pinyin4j ... -
Spring加载properties文件的两种方式
2013-10-31 10:05 0在spring中可以通过下面的方式将配置文件中的项注入到配置中 ... -
动态加载spring .xml中的bean对象
2013-10-30 15:27 0在java中如何取得spring.xml中加载的bean对象? ... -
(转)Spring mvc+hibernate+freemarker(实战)
2013-10-28 19:40 1032http://zz563143188.iteye.com/bl ... -
(转)Java之美[从菜鸟到高手演变]系列之博文阅读导航
2013-10-28 17:00 1762Java之美[从菜鸟到高手演变]系列之博文阅读导航 http: ... -
(转)openssl 制作证书和签名java方法
2013-10-28 15:03 0Win32OpenSSL_Light-0_9_8k.exe ... -
(转)面向接口编程详解
2013-10-25 12:34 5老文章,自己学习。 面向接口编程详解(一) http://w ... -
(转)Java架构师之路:JAVA程序员必看的15本书
2013-10-08 18:24 0作为Java程序员来说,最 ... -
Java获取CPU ID和磁盘ID
2013-09-25 20:18 0原文链接:http://www.rgagnon.com/jav ... -
Java编程之备用程序段
2013-09-25 14:57 0记录一些程序段,供日常备用,持续增加中…… 1. Java中 ... -
(转)Java编程之AOP
2013-09-25 14:45 0链接: http://hw19886200.iteye.com ... -
Java编程之性能优化
2013-09-25 14:28 805最近的机器内存又爆满 ... -
使用axis2传输附件
2013-09-25 10:40 1101服务端Service文件: import java.io. ... -
Java应用程序项目打包成exe文件
2013-09-23 09:16 01.程序打包 首先将程序打成Jar包,打包命 ... -
(转)Java事务处理类型及差异总结
2013-09-18 13:54 1637一、什么是Java事务 ... -
JAVA文件_加密
2013-09-13 16:09 0import java.awt.*; import java ... -
(转)Java 实现Rsa 加密
2013-09-13 16:08 0import java.io.*; public class ...
相关推荐
java.util.ConcurrentModificationException 解决方法 在使用iterator.hasNext()操作迭代器的时候,如果此时迭代的对象发生改变,比如插入了新数据,或者有数据被删除。 则使用会报以下异常: ...例如以下程序(转
**FastJson 深度解析** FastJson 是阿里巴巴开源的一款高效、功能强大的 JSON 库,它在 Java 开发中被广泛使用,特别是在处理 JSON 数据序列化与反序列化时。这个压缩包包含了 FastJson 的全部资料,对于学习和理解...
**5.2 问题:** "ConcurrentModificationException" **解决:** 在遍历集合时同时修改它会导致这个异常。解决方案包括: - **使用线程安全集合:** 使用线程安全的集合类,如`ConcurrentHashMap`。 - **迭代器的...
- **并发异常**:如ConcurrentModificationException,当多个线程访问同一资源时,如果没有适当的同步控制,可能会出现问题。使用synchronized关键字、Lock机制或并发集合来解决。 - **死锁**:多个线程互相等待...
常见的问题可能包括但不限于:空指针异常(NullPointerException)、类型转换异常(ClassCastException)、数组越界异常(ArrayIndexOutOfBoundsException)、并发修改异常(ConcurrentModificationException)等。...
5. **并发问题**:多线程编程中,共享资源的并发访问可能导致数据不一致、死锁等问题。使用synchronized关键字、volatile修饰符、Lock接口等工具管理并发访问,保证线程安全。 6. **异常处理**:Java中的异常处理是...
如果在遍历集合或数组时,修改了集合或数组的内容,这可能会引发ConcurrentModificationException异常。这种异常是在运行时抛出的,而不是在编译期。 例如,在遍历集合时,修改集合的内容可能会引发...
4. **并发问题**:在多线程环境中,不恰当的共享资源访问可能导致数据不一致,如`ConcurrentModificationException`。使用`synchronized`关键字或者并发集合可以防止这类问题。 5. **IO异常**:在处理输入/输出时,...
但是,如果我们在foreach循环中进行元素的remove/add操作,可能会出现ConcurrentModificationException。因为foreach循环不允许在遍历过程中修改数据。如果我们需要在foreach循环中进行元素的remove/add操作,我们...
10. serialVersionUID字段的修改问题:阿里巴巴禁止开发人员修改serialVersionUID字段的值,因为这个字段用于序列化版本控制,如果随意更改会导致序列化与反序列化时出现问题。正确的做法是在类的序列化形式变更时才...
- 遍历方式:推荐使用迭代器`Iterator`遍历ArrayList,而不是`for-each`循环,因为`for-each`在删除元素时可能导致ConcurrentModificationException。 以上内容涵盖了Java解析JSON的基本方法、时间戳转换、文件...
10. **ConcurrentModificationException**:在多线程环境下,当一个线程正在修改集合,而另一个线程尝试遍历同一集合时,会抛出此异常。使用并发控制或使用不可变集合来避免。 以上仅是Java环境报错中的一部分,...
6. **集合操作错误**:在遍历集合时修改集合会导致ConcurrentModificationException。使用迭代器或Collections.unmodifiableList()等方法可以避免这类问题。 7. **类型转换异常**:强制类型转换不当可能导致...
12. **ConcurrentModificationException**:在并发修改集合时,如果一个线程正在迭代集合,而另一个线程同时对集合进行修改,会出现此异常。推荐使用`CopyOnWriteArrayList`或`ConcurrentHashMap`等并发友好的集合类...
- **遍历与修改集合**:在迭代器遍历集合时修改集合会导致ConcurrentModificationException。使用Iterator的remove()方法或者CopyOnWriteArrayList/CopyOnWriteArraySet等并发友好的集合可以解决此问题。 - **集合...
面试中可能会涉及到并发修改(ConcurrentModificationException)、迭代器、集合排序、泛型、JDK新版本中集合的优化等内容。 3. **多线程**:Java多线程是常考知识点,包括线程的创建、同步、互斥、死锁,以及...
3. **并发修改异常**:当一个线程正在遍历`HashMap`时,另一个线程对其进行了修改,则可能会抛出`ConcurrentModificationException`异常。 #### 三、解决方案概述 针对以上提到的问题,有多种不同的解决方案可以...
在遍历集合时,通常推荐使用Iterator而不是直接通过集合的索引进行操作,因为这样可以避免并发修改异常(ConcurrentModificationException)。 在题目中,给出了三个练习: 1. 练习一要求简述集合框架,我们已经...
线程不安全则表示在多线程环境下,如果不采取额外的同步措施,就可能引发数据竞争和其他并发问题。 线程不安全集合: 1. `ArrayList`: 这是一个动态数组实现的列表,其添加、删除和修改操作不是线程安全的。在并发...