其他分享
首页 > 其他分享> > ArrayList等集合线程不安全!!

ArrayList等集合线程不安全!!

作者:互联网

1.ArrayList概念

ArrayList底层是数组,初始化大小为10,如果超出采用Arrays.copyOf,扩充代价高,最好之前指定容量大小。int newCapacity = oldCapacity + (oldCapacity >> 1)扩充1.5倍。线程不安全!

2.ArrayList线程不安全解决方法

List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");

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. 故障现象
java.util.ConcurrentModificationException
  1. 导致原因

并发争抢修改导致----举例子
30个人同时在签字表上签字,如果加锁,每个人只能签一次;
如果不加锁,一个人正在写,另一个人来抢,导致写入异常!

  1. 解决方案

3.1 new vector();
JDK1.0提出的,加synchronized,虽然保证了数据一致性,但是并发效率下降,故提出了ArrayList;

List<String> list = new vector();

3.2Collections.synchronizedList(new ArrayList<>());
JDK1.2工具类提出的,为了解决ArrayList的,集合工具类提供的同步方法。

List<String> list = Collections.synchronizedList(new ArrayList<>());

3.3 new CopyOnWriteArrayList();
写时复制–读写分离的思想

CopyOnWrite容器即写时复制的容器。往一个容器添加元素的时候,不直接往当前容器Object[]添加,
而是先将当前object[]进行Copy,复制出一个新的容器Object[] newElements,然后新的容器Object[] newElements里添加元素,添加完元素之后,
再将原容器的引用指向新的容setArray(newElements);
这样做的好处是可以对copyonwrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以copyonwrite容器也是一种读写分离的思想,读和写不同的容器。

缺点:可能导致读时数据不一致,由于复制数组,内存占用高。

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();
    }
}

3.集合中线程不安全还有?

3.1Set

Set<String> set = new HashSet<>();

**
* Constructs an empty <tt>HashMap</tt> with the default initial capacity
 * (16) and the default load factor (0.75).
 */
public HashMap() {
    this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}

底层使用HashMap中的key,故set不可重复,随机,而value是一个常量。
初始化大小16,加载因子是0.75;

其中加载因子是指hashmap填满的程度!

3.1.1 Set线程不安全解决方法

Collections.synchronizedSet();
new CopyOnWriteArraySet<>();

3.2HashMap解决方法

Collections.synchronizedMap();
new ConcurrentHashMap()

标签:容器,ArrayList,Object,list,newElements,线程,集合,new
来源: https://blog.csdn.net/jmkmlm123456/article/details/98462261