Java高并发程序设计(七)--JDK的并发容器

时间:2021-07-19 17:57:14

1、线程安全的HashMap

如果需要一个线程安全的HashMap ,可以使用集合工具类的synchronizedMap(Map<K,V> m)方法实现,

Collections.synchronizedMap(m);

进到方法里面,

public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
    return new SynchronizedMap<K,V>(m);
    }

它返回一个内部类,进入内部类

private static class SynchronizedMap<K,V>
    implements Map<K,V>, Serializable {

    private final Map<K,V> m;     // Backing Map
    final Object      mutex;    
    。。。。。
}

发现它是用的代理的方法来实现的,所有功能全都由传进来的Map,也就是m实现,它只负责给方法加锁。如:

public V put(K key, V value) {
        synchronized(mutex) {return m.put(key, value);}
        }
public V get(Object key) {
        synchronized(mutex) {return m.get(key);}
        }

除此方法外,还有更加专业的ConcurrentHashMap,可以在原来的博客中找到相关内容。

 

2、线程安全的List

和HashMap相似,也可以通过Collections.synchronizedList(list)来获得一个线程安全的ArrayList或者LinkedList。

同样,JDK也提供了一个CopyOnWriteArrayList来实现线程安全。

CopyOnWriteArrayList适用于读多写少的场景,对他来说读读操作完全不需要加锁,读写同时发生也不会堵塞,只要在写写同时发生时才需要同步。

在写入操作时,它会进行一次复制,然后在复制的副本上进行修改,最后用副本替换原来的数据。

 

3、数据共享通道:BlockingQueue

它是一个接口,一般用来在线程之间共享数据,有以下的具体实现:

Java高并发程序设计(七)--JDK的并发容器

下面是它的方法:

Java高并发程序设计(七)--JDK的并发容器

其中,当你put时,向队尾压进一个数据,如队列已满,则等待队列有空再进去,当你take时,如果为空,则会一直等待到不为空。