ArrayList、HashSet线程不安全集合

一、不安全示例

ArrayList是java集合框架中一个重要的类,是一个长度可变的集合。在多线程环境下的操作ArrayList是不安全的,会抛出并发修改异常ConcurrentModificationException。话不多说,上示例:

在for循环中new了十个线程,每一个线程都向list中添加元素

public class ListTest {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        for (int i = 1; i <= 10; i++) {
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(list);
            },String.valueOf(i)).start();
        }
    }
}

二、解决方案

1.Vector

List<String> list = new Vector<>();

在jdk1.0时,就发布的Vector集合,该集合中的add方法是加synchornized锁的,可以保障线程安全

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

虽然synchornized保证了线程安全,但是大大影响了性能

运行结果:

2.Collections

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

Collections是所有集合的父类,在Collections中有许多加锁的集合,这里将ArrayList改为Collections.synchronizedList(new ArrayList<>()) 使集合变安全

 运行结果:

3.CopyOnWriteArrayList

List<String> list = new CopyOnWriteArrayList<>();

CopyOnWriteArrayList是java.util.concurrent为开发者提供的一个线程安全集合,CopyOnWrite就是写入时复制 。

在多线程环境下对一个list进行操作时,读没有影响,但进行写入操作会发生覆盖问题

CopyOnWrite就是在写入的时候避免覆盖,造成数据问题

CopyOnWriteArrayList比Vector的性能要快

Vector底层add方法用的是synchornized,而CopyOnWriteArrayList底层用的是lock锁

public boolean add(E e) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            //copyOf --- > 写入时复制
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            setArray(newElements);
            return true;
        } finally {
            lock.unlock();
        }
    }

 运行结果:

三、HashSet

HashSet也是线程不安全集合,不过HashSet没有像Vector一样加锁的集合。

使HashSet线程安全的方式:

1.Collections.synchronizedSet

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

2.CopyOnWriteArraySet

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

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值