java集合不安全

java 集合不安全问题

ArrayList(线程不安全)

1. arraylist 底层实现

数组 初始长度为10

2. arraylist 线程不安全case

 public static void main(String[] args) {
        List<String> list = new ArrayList<>();

        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                list.add(UUID.randomUUID().toString().substring(0, 8));
                System.out.println(list);
            }).start();
        }
 }

出现现象

java.util.ConcurrentModificationException(并发修改异常)

导致原因

并发争枪修改导致。

参考花名册,一个人正在写,另一个人过来抢夺,导致数据不一致异常

解决办法

// 解决一
// List<String> list = new Vector()
// ArrayList 线程不安全,效率高
// Vector 线程安全,效率低
// Vector 底层源码中加了 synchronized

public static void main(String[] args) {
        List<String> list = new Vector<>();

        for (int i = 0; i < 30; i++) {
            new Thread(() -> {
                list.add(UUID.randomUUID().toString().substring(0, 8));
                System.out.println(list);
            }).start();
        }
}
// 解决二
// List<String> list = Collections.synchronizedList(new ArrayList<>());
// 性能不高 
public static void main(String[] args) {
        List<String> list = Collections.synchronizedList(new ArrayList<>());

        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                list.add(UUID.randomUUID().toString().substring(0, 8));
                System.out.println(list);
            }).start();
        }
}
// 解决三
// List<String> list = new CopyOnWriteArrayList<>();
public static void main(String[] args) {
        List<String> list = new CopyOnWriteArrayList<>();

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

解决方法三:

List<String> list = 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(element, len + 1);
        newElements[len] = e;
        setArray(newElements);
        return true;
    } finally {
        lock.unlock();
    }
}

HashSet(线程不安全)

与上面同理

Collections.synchronizedSet(new HashSet())
// 性能不高 
new CopyOnWriteArraySet()

hashset 底层 hashmap

key add 的值

value object present = new object();

HashMap(线程不安全)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NzPnmHO7-1609729333684)(C:\Users\pikaqiu\AppData\Roaming\Typora\typora-user-images\1609727707851.png)]

Collections.synchronizedMap(new HashMap())
// 性能不高 

HashTable(线程安全)

内部有上锁的控制 synchronized

底层实现是哈希表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q2gDE4Tc-1609729333690)(C:\Users\pikaqiu\AppData\Roaming\Typora\typora-user-images\1609727341710.png)]

ConcurrentHashMap(线程安全)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GjyBmKks-1609729333696)(C:\Users\pikaqiu\AppData\Roaming\Typora\typora-user-images\1609728182225.png)]

对于hashtable,hashmap,concurrenthashmap 如何选择

优先选择hashmap, 如何不是多个资源访问一个线程的情况,优先选用hashmap, 局部变量,不是全局变量

(线程安全)

[外链图片转存中…(img-GjyBmKks-1609729333696)]

对于hashtable,hashmap,concurrenthashmap 如何选择

优先选择hashmap, 如何不是多个资源访问一个线程的情况,优先选用hashmap, 局部变量,不是全局变量

是全局变量,多个线程共享访问选择ConcurrentHashMap

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值