文章目录
提示:以下是本篇文章正文内容,下面案例可供参考
一、List
代码如下(示例):
publicclassZZZZZZZZZZ{publicstaticvoidmain(String[] args){// ArrList 非线程安全的集合List<String> list1 =newArrayList<>();for(int i =0; i <30; i++){newThread(()->{// 多个线程同时向 ArrayList 添加元素
list1.add(UUID.randomUUID().toString().substring(0,8));System.out.println(list1);}).start();}}}
输出结果
Exception in thread “Thread-1” Exception in thread “Thread-0” Exception in thread “Thread-4” Exception in thread “Thread-25” Exception in thread “Thread-23” Exception in thread “Thread-17” Exception in thread “Thread-18” Exception in thread “Thread-27”
java.util.ConcurrentModificationException
,并发修改异常,由于ArrayList 不是线程安全的容器,多个线程并发添加元素,会导致竞争现象,最终产生该异常。
故障出现
java.util.ConcurrentModificationException
导致原因
多线程并发争抢修改导致
解决方法
- 使用线程安全的容器,例如:Vector,在该类中每个方法都加上了 synchronized,不会导致线程安全问题,但是由于锁的粒度太细,会导致程序的速度较慢。
- 使用集合工具类的线程安全的方法,如:
static<T>List<T>Collections.synchronizedList(List<T> list)
- juc 下面的 CopyOnWriteArrayList,该类使用使用 ReentrantLock 加锁解锁,每次添加新元素就会加锁,然后开辟比旧数组多1的空间,将原数组全部拷贝进去,再将新元素加到最后一个位置。由于每次添加元素都会拷贝原数组,如果原数组很大,就会对内存资源造成很大的消耗,因此适合读多写少的场景。源码如下:
publicbooleanadd(E e){finalReentrantLock lock =this.lock;
lock.lock();try{Object[] elements =getArray();int len = elements.length;Object[] newElements =Arrays.copyOf(elements, len +1);
newElements[len]= e;setArray(newElements);returntrue;}finally{
lock.unlock();}}
二、Set
代码如下(示例):
publicclassZZZZZZZZZZ{publicstaticvoidmain(String[] args){// 非线程安全的 HashSetSet<String> set =newHashSet<>();for(int i =0; i <30; i++){newThread(()->{
set.add(UUID.randomUUID().toString().substring(0,8));System.out.println(set);}).start();}}}
故障出现
java.util.ConcurrentModificationException
导致原因
多线程并发争抢修改导致
解决方法
- 使用集合工具类的线程安全的方法,如:
static<T>Set<T>Collections.synchronizedList(Set<T> s)
- juc 下面的 CopyOnWriteArraySet,底层还是 CopyOnWriteArrayList,源码的构造方法如下:
publicCopyOnWriteArraySet(){
al =newCopyOnWriteArrayList<E>();}
三、Map
代码如下(示例):
publicclassZZZZZZZZZZ{publicstaticvoidmain(String[] args){// 非线程安全的 HashMapMap<String,String> map =newHashMap<>();for(int i =0; i <30; i++){newThread(()->{
map.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0,8));System.out.println(map);}).start();}}}
故障出现
java.util.ConcurrentModificationException
导致原因
多线程并发争抢修改导致
解决方法
- 使用线程安全的容器,如:ConcurrentHashMap
- 使用集合工具类的线程安全的方法,如:
static<K,V>Map<K,V>Collections.synchronizedMap(Map<K,V> m)
版权归原作者 学习愚公 所有, 如有侵权,请联系我们删除。