集合

我们知道ArrayList类是线程不安全的,如果运行以下代码:

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

image.png

会有ConcurrentModificationException

Vector则是线程安全的:

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

这是由于vector的方法是加了synchronized

image.png

还可以用Collections.synchronizedList(new ArrayList<>()) :

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

还有一种方法,就是使用CopyOnWriteArrayList

public class un_list {  
    public static void main(String[] args) {  
//        ArrayList<String> list = new ArrayList<>();  
//        Vector<String> list = new Vector<>();  
//        List<String> list = Collections.synchronizedList(new ArrayList<>());  
        List<String> list = new CopyOnWriteArrayList<>();  
        for (int i = 0; i < 100; i++) {  
            new Thread(() -> {  
                list.add(UUID.randomUUID().toString().substring(0, 5));  
                System.out.println(list);  
            }).start();  
        }  
    }  
}

 CopyOnWriteArrayList 是通过 Copy-On-Write(COW),即写时复制的思想来通过延时更新的策略实现数据的最终一致性,并且能够保证读线程间不阻塞。当然,这要牺牲数据的实时性

通俗的讲,CopyOnWrite 就是当我们往一个容器添加元素的时候,不直接往容器中添加,而是先复制出一个新的容器,然后在新的容器里添加元素,添加完之后,再将原容器的引用指向新的容器。多个线程在读的时候,不需要加锁,因为当前容器不会添加任何元素。

如何实现的?点进源码看看:

image.png image.png image.png transient volatile是啥?那先放到一边吧,总之就是用这个实现了并发安全呗。

那为什么要用CopyOnWriteArrayList不用vector呢?上面我们展示了vectoradd方法,下面看看CopyOnWriteArrayList的读写: image.png

image.png 写通过同步代码块保证并发,读则没有加锁。所以读的性能非常高。