多线程中集合不安全问题及解决方案

在java中,存在很多集合,比如ArrayList、LinkedList、HashSet、HashMap等。如何保证它们在多线程下的集合安全性呢?

List集合

测试

public class ListTest {
    public static void main(String[] args) {
//        ArrayList<String> list = new ArrayList<>();
//       1. List<String> list = new Vector<>();
//       2. List<String> list = Collections.synchronizedList(new ArrayList<>());
//       3. List<String> list = new CopyOnWriteArrayList<>();

        ArrayList<String> list = new ArrayList<>();
        for (int i = 1; i <= 30; i++) {
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(list);
            },String.valueOf(i)).start();
        }

    }
}

结果

报错:java.util.ConcurrentModificationException

解决方案

使用List list = new Vector<>();
实际是使用了synchronized实现加锁使线程安全。

在这里插入图片描述

使用List list = Collections.synchronizedList(new ArrayList<>());
实际也是新建一个synchronized锁的List。

在这里插入图片描述

使用List list = new CopyOnWriteArrayList<>();
实际是使用ReentrantLock锁,先对需要写入的数据进行复制,写完之后再合并,实现了读写分离,读的是同一个数据,而写的是不同的数据,避免写入混乱。

在这里插入图片描述

Set集合

测试

public class SetTest {
    public static void main(String[] args) {
//        Set<String> set = new HashSet<>();
//        1. Set<String> set = Collections.synchronizedSet(new HashSet<>());
//        2. Set<String> set = new CopyOnWriteArraySet();

        Set<String> set = new HashSet<>();
        for (int i = 1; i <= 30; i++) {
            new Thread(()->{
                set.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(set);
            },String.valueOf(i)).start();
        }
    }
}

结果

报错:java.util.ConcurrentModificationException

解决方案

使用Set set = Collections.synchronizedSet(new HashSet<>());
新建一个synchronized锁的Set。

使用Set set = new CopyOnWriteArraySet();
本质是使用ReentrantLock锁,先对需要写入的数据进行复制,写完之后再合并,实现了读写分离,读的是同一个数据,而写的是不同的数据,避免写入混乱。

HashSet的底层就是HashMap
在这里插入图片描述
在这里插入图片描述
add方法本质就是map,因为map的key不能重复,因此set里的键也不重复。

Map集合

测试

public class MapTest {
    public static void main(String[] args) {
        //默认等价于什么? Map<String, Object> map = new HashMap<String, Object>(16,0.75);
        //初始化容量 16 / 加载因子 0.75
//        Map<String, String> map = new HashMap<String, Object>();
//        1. Map<String, String> map = Collections.synchronizedMap(new HashMap<>());
//        2. Map<String, String> map = new ConcurrentHashMap<>();

        Map<String, String> map = new HashMap<String, String>();
        for (int i = 1; i <= 30; i++) {
            new Thread(()->{
                map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0,5));
                System.out.println(map);
            },String.valueOf(i)).start();
        }
    }
}

结果

报错:java.util.ConcurrentModificationException

解决方案

使用Map<String, String> map = Collections.synchronizedMap(new HashMap<>());
新建一个synchronized锁的Map。

使用Map<String, String> map = new ConcurrentHashMap<>();

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值