集合 多线程不安全怎么解决?List / Set / Map

List

集合类我们平时最常用的就是ArrayList<>,单线程情况下,性能较高。

但是碰到多线程的时候就很容易炸,因为它是线程不安全的!

为何不安全?因为它的add()方法没有锁!

public boolean add(E e) {
    add(size(), e);
    return true;
}

所以在多线程并发的情况下就可能出现ConcurrentModificationException并发修改异常!

怎么解决呢?

1.vector

既然这个ArrayList是线程不安全的集合,我们直接用vector这种线程安全的集合不就行了?

    public synchronized boolean add(E e) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = e;
        return true;
    }

行是行,但vector是jdk1.0版本就出了,而ArrayList却在后面的1.2版本才出?为何多此一举呢?
主要是因为vector的效率太低了!别急,还有其他方法!

2.集合工具类Collections.synchronizedList(list)

集合工具类Collections就提供了帮你锁住的list方法,你就可以把arrayList丢进去加个锁!

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

3.JUC工具类concurrent包中的C opyOnWirteArrayList()

提供了一个写时读的集合,可以说是读写分离,其他线程在读取内存中的数据时并不会被影响。

    import java.util.concurrent.CopyOnWriteArrayList;
	---
    List list = new CopyOnWriteArrayList();

将目标集合拷贝出来后,用lock锁住,扩容一个长度,将新值丢到新扩容的下标后,再将这个集合替换掉原来的数组,之后释放锁

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

Set

set之所以不会有重复的元素,如HashSet就是因为它的底层其实是包装了一个HashMap。

每次将值放进key中,value则固定放了一个名为present的Object常量。

这也是为什么set在add时只需一个参数,而map需要两个参数的解决方法!

那么Set不安全怎么解决?一样的套路,一样的技巧,跟list都是collection的子类,举一反三!

1.集合工具类Collections.synchronizedSet(HaspSet)

Set<Object> set = Collections.synchronizedSet(new HashSet<>());

同样的这个集合工具类也提供了一个方法直接锁住!

2.JUC 工具类CopyOnWriteArraySet()

CopyOnWriteArraySet set= new CopyOnWriteArraySet<>();

其实底层就是套了一个上面的CopyOnWriteArrayList对象!

public CopyOnWriteArraySet() {
    al = new CopyOnWriteArrayList<E>();
}

Map

虽然Collections也提供了一个synchronizedMap(),但在原子性上显然不够完美,HashMap就直接使用ConcurrentHashMap()即可!

ConcurrentHashMap map = new ConcurrentHashMap();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值