线程安全的集合类

来源:互联网 发布:ubuntu 脚本使用教程 编辑:程序博客网 时间:2024/05/16 05:58

java中常用的线程安全集合类

这里写图片描述

java.util.Hashtable

HashTable的实例中有两个参数影响其性能:初始容量和加载因子
初始容量:Hash表创建时的容量
加载因子:对hash表在其容量自动增加之前可以达到多满的一个尺度,通常默认是0.75

Hashtable 的函数都是同步的,意味着它是线程安全的。它的key和value都不可以为null。此外,hashtable中的映射不是有序的。
线程安全原理–源码如下

public class Hashtable<K,V>    extends Dictionary<K,V>    implements Map<K,V>, Cloneable, java.io.Serializable {    private transient Entry<?,?>[] table;    public synchronized V put(K key, V value) {        ....此处省略实现    }    public synchronized V remove(Object key) {        ....此处省略实现    }    public synchronized void putAll(Map<? extends K, ? extends V> t) {        ....此处省略实现    }     public synchronized V get(Object key) {        ....此处省略实现     }    public synchronized void clear() {        ....此处省略实现    }}

从源码中可以看出,hashtable提供的几个主要方法,每个方法本身都是synchonizedde ,不会出现两个线程同时对数据进行操作的情况,因此是线程安全的

java.util.concurrent.ConcurrentHashMap

ConcurrentHashMap 继承AbstractMap 实现ConcurrentMap

public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>    implements ConcurrentMap<K,V>, Serializable {    static class Segment<K,V> extends ReentrantLock implements Serializable {        private static final long serialVersionUID = 2249069246763182397L;        final float loadFactor;        Segment(float lf) { this.loadFactor = lf; }    }}

java.util.concurrent.CopyOnWriteArrayList

CopyOnWriteArrayList 中的set、add、remove等方法,都使用了ReentrantLock的lock来加锁,unlock来解锁
当增加元素的时候使用Arrays.copyOf()来拷贝副本,在副本上增加元素,然后改变原来引用的指向副本。读操作不需要加锁,因此,CopyOnWriteArrayList类是一个线程安全的List接口实现,这对于读操作远远多于写操作的应用非常适合,特别是在并发的情况下,可以提供高性能的并发读取,并保证读取的内容一定是正确的,不受多线程并发问题的影响。

public class CopyOnWriteArrayList<E>    implements List<E>, RandomAccess, Cloneable, java.io.Serializable {    final transient ReentrantLock lock = new ReentrantLock();    private E get(Object[] a, int index) {        return (E) a[index];    }}

java.util.concurrent.CopyOnWriteArraySet

原理同CopyOnWriteArrayList

CopyOnWrite机制介绍

CopyOnWrite容器即写是复制的容器。通俗的理解就是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素后,再将原容器的引用指向新的容器。这样做的好处就是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素
所以,CopyOnWrite容器也是一种读写分离的思想。读和写不容的容器。
我们从CopyOnWriteArrayList之前的分析和源码中可以看出,ArrayList里添加元素,在添加的时候是需要加锁的,否则多线程写的时候会copy出多个副本出来
读的时候不需要加锁,如果都的时候有多线程正在像ArrayList中添加数据,还是会读到旧的数据,因为写的时候不会锁住旧的ArrayList

1、使用场景:读多写少
2、使用注意点:
a、减少扩容开销;b、使用批量添加

缺点:
a、内存占用问题
b、数据一致性问题

Vector

与ArrayList不同,Vector中的操作是线程安全的,他是利用synchronized同步显示锁的机制实现的,实现机制类似Hashtable

StringBuffer和StringBuilder

StringBuffer:线程安全,效率不高,方法上使用synchronized实现线程安全机制

StringBuilder:线程不安全,效率相对高

0 0