4.并发容器
简介
ConcurrentHashMap;//线程安全的HashMap
CopyOnWriteArrayList;//在读多写少的场合性能很好,远优于vector
ConcurrentLinkedQueue;//线程安全的LinkedList
BlockingQueue;//阻塞队列,适合作数据共享的通道
ConcurrentSkipListMap;//这是一个Map,使用跳表进行快速查找
此外Vector也是线程安全的,Collections工具类可以帮助我们将任意集合包装成线程安全的集合
一. 线程安全的HashMap
1. 使用Collections工具类
Map<Object, Object> m= Collections.synchronizedMap(new HashMap<>());
其原理为通过mutex对m进行互斥操作,比如Map.get()
public V get(Object key){
synchronized(mutex){return m.get(key);}
}
虽然这个包装的map能满足线程安全的要求,但是其性能很差,无论是对map的读或者锁,都需要获得mutex的锁,这会导致所有对map的操作都进入等待状态,直到mutex可用
2.ConcurrentHashMap
专门对并发进行了优化,适合多线程的场合
二、线程安全的List
1.使用Collections工具类
List<String> l = Collections.synchronizedList(new LinkedList<>());
2.高效读写的队列 ConcurrentLinkedQueue
等待
三、高效读取:不变模式下的CopyOnWriteArrayList
类似读写锁,但是其读写线程之间不会相互阻塞,只有写和写之间需要进行同步等待
当这个list需要修改时,并不修改原有内容,而是对原有数据进行一次复制,对副本进行修改,然后在用修改完的副本替换原来的数据。并且因为array变量时volatile类型,因此修改完后,读取线程可以立即察觉到这个修改
四、数据共享通道BlockingQueue
与前面几种容器不同,BlockingQueue是一个接口,而不是具体实现,他的主要实现有很多,我们主要介绍ArrayBlockingQueue和LinkedBlockingQueue
ArrayBlockingQueue
基于数组实现,属于有界队列,大小在初始化时指定
LinkedBlockingQueue
基于链表实现,属于无界队列,大小动态变化
BlockingQueue之所以适合作为数据共享的通道,关键在于Blocking,Blocking是阻塞的意思,系统如何知道有新消息在等待呢,可以让系统定时查看队列,但是很明显浪费资源,BlockingQueue则是当有消息来时,他会将线程唤醒,省去了系统开销
ArrayBlockingQueue
向队列中压入元素可使用offer和put方法
offer方法是若有位置则进入,否则返回false
put方法是有位置进入,否则等待,知道有空位
从队列弹出元素有poll和take方法,poll类似offer,而take类似put方法
ArrayBlockingQueue内部类似循环队列,有两个元素takeIndex和putIndex,总是从takeIndex取,从putIndex进。
五、随机数据结构:跳表(SkipList)
类似b树