在集合遍历的时候,向集合中添加元素
这里的错误叫做fail-fast机制,当多个线程对同一集合的内容进行操作时,就可能会产生fail-fast事件
当modCount的数量和expectedModCount的数量不一致时,就会抛出上面的异常
集合元素添加产生异常的代码
package com.java.test.copyonwritearraylistdemo; /** * @Description: * @Author: Yourheart * @Create: 2022/12/2 15:34 */ public class TestCopyOnWriteArrayList { public static void main(String[] args) { HelloThread h = new HelloThread(); for (int i = 0; i < 10; i++) { new Thread(h).start(); } } }
package com.java.test.copyonwritearraylistdemo; import lombok.extern.slf4j.Slf4j; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; /** * @Description: * @Author: Yourheart * @Create: 2022/12/2 15:35 */ @Slf4j public class HelloThread implements Runnable { private static List<String> list = Collections.synchronizedList(new ArrayList<>()); static { list.add("aaa"); list.add("bbb"); list.add("ccc"); } @Override public void run() { Iterator<String> iterator = list.iterator(); while (iterator.hasNext()){ String next = iterator.next(); list.add(next+"123"); } } }
引入CopyOnWriteArrayList
不在使用modCount和ExpectModCount进行比较
代码改动部分
package com.java.test.copyonwritearraylistdemo; import lombok.extern.slf4j.Slf4j; import java.util.Iterator; import java.util.concurrent.CopyOnWriteArrayList; /** * @Description: * @Author: Yourheart * @Create: 2022/12/2 15:35 */ @Slf4j public class HelloThread implements Runnable { private static CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(); static { list.add("aaa"); list.add("bbb"); list.add("ccc"); } @Override public void run() { Iterator<String> iterator = list.iterator(); while (iterator.hasNext()){ String next = iterator.next(); list.add(next+"123"); } } }
不过问题也很明显,适合读数据比较多,写数据比较少的情况,会产生数据一致性问题
这里读取操作没有加锁,那么读数据就会很快,同时读取到的可能是老数据,而不是最新数据的原因
最后总结下优缺点
优点:读多写少性能优秀,线程安全读写分离
缺点:内存占用大,数据一致性问题
标签:java,CopyOnWrite,iterator,简单,list,util,add,使用,import From: https://www.cnblogs.com/q202105271618/p/16951523.html