1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 多线程并发下集合不安全类-ArrayList

多线程并发下集合不安全类-ArrayList

时间:2021-03-27 22:39:14

相关推荐

多线程并发下集合不安全类-ArrayList

ArrayList集合在多线程并发操作下是不安全的

ArrayList集合在并发操作下会发生异常:故障现象java.util.ConcurrentModificationException

导致原因 多线程对集合的并发操作导致并发修改异常的产生

解决方案

1、使用Vector(加synchronized)

2、使用集合工具类里的Collections.synchronizedList(new ArrayList<>())使用同步代码块

3、CopyOnWriteArrayList(写时复制ReentrantLock

CopyOnWriteArrayList使用的思想是读写分离

public class Demo3 {public static void main(String[] args) {//List<String> list = new ArrayList<>();//List<String> list = Collections.synchronizedList(new ArrayList<>());//collections是集合接口的工具类,collection是集合的接口/*** 写时复制* CopyOnWrite容器即写时复制的容器,往一个容器添加元素的时候,不直接往当前容器object[]* 而是先将当前容器object[]进行复制,复制出一个新的object[] new Elements,然后新的容器object[] new Elements里添加元素* 添加完元素之后,再将原容器的引用指向新的容器,这样做的好处是可以对容器进行并发的读,* 而不需要加锁,因为当前容器不会添加任何元素,所以copyonwrite是一种读写分离的思想,读和写不同的容器*/List<String> list = new CopyOnWriteArrayList<>();for (int i = 1; i <= 30; i++) {new Thread(()->{list.add(UUID.randomUUID().toString().substring(0, 10));System.out.println(list);}).start();}}

package com.zhbit.juc;import lombok.extern.slf4j.Slf4j;import java.util.*;import java.util.concurrent.CopyOnWriteArrayList;import java.util.concurrent.TimeUnit;//ArrayList集合类不安全//故障现象 java.util.ConcurrentModificationException//导致原因 多线程对集合的并发操作导致并发修改异常的产生//解决方案 Vector(加synchronized)--->Collections.synchronizedList(new ArrayList<>())使用同步代码块--->CopyOnWriteArrayList(写时复制ReentrantLock)//优化建议@Slf4jpublic class CopyOnWriteArrayListExample {public static void main(String[] args) throws InterruptedException {CopyOnWriteArrayListExample.testArrayList();// CopyOnWriteArrayListExample.testVector();// CopyOnWriteArrayListExample.testCollectionsSynchronizedList();// CopyOnWriteArrayListExample.testCopyOnWriteArrayList();TimeUnit.SECONDS.sleep(3);}static void testArrayList() {List list = new ArrayList(); //不安全会产生 java.util.ConcurrentModificationException异常for (int i = 1; i <= 30; i ) {new Thread(() -> {list.add(UUID.randomUUID().toString().substring(0, 8));System.out.println(list);}, String.valueOf(i)).start();}}//以下是三种解决方法static void testVector() {List list = new Vector();//1、使用Vector代替ArrayListfor (int i = 1; i <= 30; i ) {new Thread(() -> {list.add(UUID.randomUUID().toString().substring(0, 8));System.out.println(list);}, String.valueOf(i)).start();}}static void testCollectionsSynchronizedList() {//2、使用集合工具类的 Collections.synchronizedList解决List list = Collections.synchronizedList(new ArrayList<>());for (int i = 1; i <= 30; i ) {new Thread(() -> {list.add(UUID.randomUUID().toString().substring(0, 8));System.out.println(list);}, String.valueOf(i)).start();}}static void testCopyOnWriteArrayList() {//3、使用CopyOnWriteArrayList(写时复制ReentrantLock)List list = new CopyOnWriteArrayList();for (int i = 1; i <= 30; i ) {new Thread(() -> {list.add(UUID.randomUUID().toString().substring(0, 8));System.out.println(list);}, String.valueOf(i)).start();}}}

源码

1、Vector添加操作

使用了synchronized,底层关键字,重量级锁,会阻塞其它线程

/*** Appends the specified element to the end of this Vector.** @param e element to be appended to this Vector* @return {@code true} (as specified by {@link Collection#add})* @since 1.2*/public synchronized boolean add(E e) {modCount ;ensureCapacityHelper(elementCount 1);elementData[elementCount ] = e;return true;}

2、Collections.synchronizedList添加操作

使用synchronized同步代码块

public boolean add(E e) {synchronized (mutex) {return c.add(e);}}

3、CopyOnWriteArrayList的添加操作

使用了ReentrantLock锁,这是JavaAPI层面的锁,属于轻量级的锁,会阻塞其它线程

/*** Appends the specified element to the end of this list.** @param e element to be appended to this list* @return {@code true} (as specified by {@link Collection#add})*/public boolean add(E e) {final ReentrantLock 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);return true;} finally {lock.unlock(); //释放锁}}

ArrayList剖析

底层数据结构:Object类型的数组结构

数组的的默认值:既然底层数据结构是Object类型的数组结构,那么数组是一段连续的内存空间

HashSet剖析

底层数据结构: 底层数据结构是HashMap

添加操作

HashSet的添加操作使用的是HashMapput操作,来保证数据的唯一性,因为HashMap的键是不可重复的

Collections工具类

CopyOnWriteArrayList写时复制

ConcurrentHashMap`底层并不是用写时复制的思想来控制多线程并发安全的,而是直接用`Node`数组 链表 红黑树的数据结构来实现,并发控制使用`Synchronized`和`CAS`来操作,整个看起来就像是优化过且线程安全的`HashMap

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。