0
点赞
收藏
分享

微信扫一扫

JAVA-集合

程序员阿狸 2022-02-11 阅读 127
java集合

1、不安全

ArrayList、HashSet、HashMap不安全的

2、原因

ArrayList 的add()方法没加synchronized (同步锁)关键字

HashSet 的底层原理是HashMap,add方法调用的就是map的put方法,key就是add的元素,值是Object常量

3、会出现的错误

java.util.ConcurrentModificationException //并发异常

4、解决

1)Vector()

使用Vector()方法 add方法加了synchronized

2)Collections.synchronizedList()

把ArrayList转换成线程安全的集合,数据量小的

3)使用CopyOnWriteArrayList<>() 多线程

CopyOnWriteArrayList() 原理就是先加锁,然后复制原先数据。获得原先数据的长度加一,为现在新的数据,原数据供大家读,不能写
 等新的数据设置进去后。释放锁,后面的人读新的数据并且,用新的数据再去做写入。

总结:

ArrayList()----> CopyOnWriteArrayList();

HashSet()----->CopyOnWriteArraySet();

HashMap()----->ConcurrentHashMap<>();

代码:

package com.cb.demo.example;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * 请举例说明集合类是不安全的
 *
 * 1 故障现象
 *         java.util.ConcurrentModificationException
 * 2 导致原因
 *
 * 3 解决方案
 *         1)使用Vector() add方法加synchronized 保证数据一致性,性能下降
 *         2)使用Collections.synchronizedList() 把ArrayList转换成线程安全的集合,数据量小的  单线程
 *         3)使用CopyOnWriteArrayList<>() 多线程
 * 4 优化建议
 *
 *
 *
 * 总结
 * 写时复制
 * CopyOnWrite容器即写时复制的容器,往一个容器添加元素的时候,不直接往当前容器Object[]添加,而是先将当前容器Object[]进行Copy,
 * 复制出一个新的容器Object[] newElements,然后新的容器Object[]  new Elements里面添加元素,添加元素之后
 * 再将原容器的引用指向新的容器setArray(newElements);这样锁的好处是可以对CopyOnWrite容器进行并发的读
 * 而不需要加锁,因为当前容器不会添加任何元素,所以CopyOnWrite容器也是一中读写分离的思想,读和写不同的容器
 *
 *
 * ArrayList 有序有重复
 * Hash 无序无重复
 */
public class NotSafeDemo {
    public static void main(String[] args) {


        /**
         *
         *
         *
         * HashMap 初始值大小是16,默认加载因子是0.75   加载因子一般够用。但是初始值大小够用
         *
         *  new 一个HashMap初始大小是16,当大小到达16*0.75=12是,会自动扩容 ,每次扩容为2^n+1 2^4=16 2^5= 32
         *
         * Constructs an empty <tt>HashMap</tt> with the default initial capacity
         *      * (16) and the default load factor (0.75)
         *
         *  ArrayList扩容为原来的一半,HashMap扩容为原来的一倍
         *
         *
         *    Node<K,V>[] tab; Node<K,V> p; int n, i;
         *
         *      Node<K,V> next;
         *  node节点,数组+(单向)链表
         */
        Map<String,String> map=new ConcurrentHashMap<>();//Collections.synchronizedMap();//new HashMap<>();
        for (int i = 0; i <30 ; i++) {
            new Thread(()->{
                map.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0,8));
                System.out.println(map);
            },String.valueOf(i)).start();
        }

        new HashMap<>();
    }

    private static void setNotSafe() {
        /**
         * HashSet 底层是HashMap();  add方法调用的就是map的put方法,key就是add的元素,值是Object常量
         *
         *  public HashSet() {
         *         map = new HashMap<>();
         *     }
         *
         *  public boolean add(E e) {
         *         return map.put(e, PRESENT)==null;
         *     }
         *
         *  private static final Object PRESENT = new Object();
         */
        Set<String> set= new CopyOnWriteArraySet();//Collections.synchronizedSet(new HashSet<>());//new HashSet<>();
        for (int i = 0; i <30 ; i++) {
            new Thread(()->{
                set.add(UUID.randomUUID().toString().substring(0,8));
                System.out.println(set);
            },String.valueOf(i)).start();
        }
    }

    private static void listNotSafe() {
         /* List<String> list=Arrays.asList("a","b","c");
        list.forEach(System.out::println);
*/

        /**
         * public synchronized boolean add(E e)  Vector的add方法加了 synchronized 所有并发add不会报错 但是性能下降
         *
         *  public boolean add(E e)  ArrayList的add方法没有加 synchronized 所以并发add会报错
         *
         *
         * CopyOnWriteArrayList() 原理就是先加锁,然后复制原先数据。获得原先数据的长度加一,为现在新的数据,原数据供大家读,不能写
         * 等新的数据设置进去后。释放锁,后面的人读新的数据并且,用新的数据再去做写入。
         * 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();
         *         }
         *     }
         *
         */

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

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

}
举报

相关推荐

Java-集合

JAVA-框架①集合

Java-集合框架

JAVA-集合框架

Java-集合/容器

java- Set集合特点

0 条评论