list,set,map集合线程不安全情况及其解决

List集合:
在main方法中造10个线程,每个线程对list集合进行添加和输出操作。

ArrayList<String> list = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(Thread.currentThread().getName() + "线程, " + list);
            },String.valueOf(i)).start();
        }

输出结果:
在这里插入图片描述
发现会报异常:ConcurrentModificationException,这个异常时多线程读写异常。
然后我们使用方法将list集合变成线程安全的:
方法一:
使用Collections工具类:
jdk8.0文档:
在这里插入图片描述
代码演示:

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

在这里插入图片描述
输出结果:
在这里插入图片描述
方式二:
使用java.util.concurrent包下的CopyonWriteArrayList:

CopyOnWriteArrayList list = new CopyOnWriteArrayList();

在这里插入图片描述
输出:
在这里插入图片描述


set及map集合, 可以有三种解决方式: 方式一:使用古老实现类:Vector或者Hashtable

演示代码:不安全:

//Set集合:
        HashSet<String> set = new HashSet<>();

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

在这里插入图片描述
方式一:使用古老实现类Vector:

Vector<String> vector = new Vector<>();

输出:
在这里插入图片描述

方式二:使用Collections集合类:

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

输出:
在这里插入图片描述
方式三:使用CopyOnWriteArraySet

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

Map集合:
方式一:使用古老实现类:Hashtable

Hashtable<String, String> table= new Hashtable<>();

方式二:使用Collections工具类:

Map<String, String> map = Collections.synchronizedMap(map1);

方式三:使用ConcurrentHashMap

ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();

对于上面这些类,一般推荐使用juc包下的并发实现类,第一:古老实现类Vector,Hashtable时jdk1.0时的,底层都是使用了synchronized来解决并发,效率较低。 第二:使用Collections工具类,是从jdk1.2版本开始的,实际上底层还是使用的synchronized来解决,效率低。 使用java.util.concurrent包下的CopyOnWriteArryList类等,它实际上时复制读写,不是全区段加锁,是分段锁,性能较好。

整体演示代码:

public class ThreadDemo4 {

    public static void main(String[] args) {

    //List集合
        //方式一:使用Collections工具类:
//        ArrayList<String> list1 = new ArrayList<>();
//        List<String> list = Collections.synchronizedList(list1);

        //方式二:使用juc包下的
//        CopyOnWriteArrayList list = new CopyOnWriteArrayList();
//
//        for (int i = 0; i < 10; i++) {
//            new Thread(()->{
//                list.add(UUID.randomUUID().toString().substring(0,5));
//                System.out.println(Thread.currentThread().getName() + "线程, " + list);
//            },String.valueOf(i)).start();
//        }


    //Set集合:
        HashSet<String> set1 = new HashSet<>();
        //方式一:使用古老实现类:Vector
//        Vector<String> vector = new Vector<>();

        //方式二:使用Collections集合类
//        Set<String> set = Collections.synchronizedSet(set1);

        //方式三:使用CopyOnWriteArraySet
//        CopyOnWriteArraySet<String> set = new CopyOnWriteArraySet<>();
//        for (int i = 0; i < 30; i++) {
//            new Thread(()->{
//                set.add(UUID.randomUUID().toString().substring(0,5));
//                System.out.println(Thread.currentThread().getName() + "线程, " + set);
//            },String.valueOf(i)).start();
//        }


    //Map集合
        HashMap<String, String> map1 = new HashMap<>();

        //方式一:使用古老实现类Hashtable
//        Hashtable<String, String> table = new Hashtable<>();

        //方式二:使用Collections集合类
//        Map<String, String> map = Collections.synchronizedMap(map1);

        //方式三:使用ConcurrentHashMap
        ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();
        for (int i = 0; i < 30; i++) {
            String key = String.valueOf(i);
            new Thread(()->{
                map.put(key,UUID.randomUUID().toString().substring(0,5));
                System.out.println(Thread.currentThread().getName() + "线程, " + map);
            },String.valueOf(i)).start();
        }
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值