java并发容器基本可以分为4个,list,map,set,queue,如下如:
1
1 list
只有一个实现 CopyOnWriteArrayList ,顾名思义就是写的时候会将共享变量新复制一份出来,这样做的好处是读操作完全无锁。
但是新插入的数据不会立即更新,对源数据的增,删,改是没用的。
适用于读多写少
2 Map
Map 接口的两个实现是 ConcurrentHashMap 和 ConcurrentSkipListMap,它们从应用的角度来看,主要区别在于ConcurrentHashMap 的 key 是无序的,而 ConcurrentSkipListMap 的 key 是有序的。所以如果你需要保证 key 的顺序,就只能使用 ConcurrentSkipListMap。
使用 ConcurrentHashMap 和 ConcurrentSkipListMap 需要注意的地方是,它们的 key 和 value 都不能为空,否则会抛出NullPointerException
这个运行时异常。下面这个表格总结了 Map 相关的实现类对于 key 和 value 的要求,你可以对比学习。
都是使用的分段锁策略。具体策略为:每个map都有一个segment,类似于map结构,当存数据的时候,先通过hash算法找到对应的segment,在通过hash算法找到segment中下标,存入对应数据,只需要锁一个segment就好,不需要锁住全表。
3 set
CopyOnWriteArraySet 和 ConcurrentSkipListSet
4 队列
从俩个维度分析,一个维度是阻塞与非阻塞,所谓阻塞指的是当队列已满时,入队操作阻塞;当队列已空时,出队操作阻塞。另一个维度是单端与双端,单端指的是只能队尾入队,队首出队;而双端指的是队首队尾皆可入队出队。Java 并发包里阻塞队列都用 Blocking 关键字标识,单端队列使用 Queue 标识,双端队列使用 Deque 标识。
使用put和take操作,其他操作不能保证线程安全
1 单端阻塞队列:
ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue、LinkedTransferQueue、PriorityBlockingQueue 和 DelayQueue。内部一般会持有一个队列,这个队列可以是数组(其实现是 ArrayBlockingQueue)也可以是链表(其实现是 LinkedBlockingQueue);甚至还可以不持有队列(其实现是 SynchronousQueue),此时生产者线程的入队操作必须等待消费者线程的出队操作。
LinkedTransferQueue 融合 LinkedBlockingQueue 和 SynchronousQueue 的功能,性能比 LinkedBlockingQueue 更好
PriorityBlockingQueue 支持按照优先级出队;无界,通过堆数据结果来实现。
DelayQueue 支持延时出队。无界,通过堆数据结构来实现
SynchronousQueue :是一个不存储元素的队列,每一个put操作必须等改一个take操作,否则不能进行添加
SynchronousQueue<Integer> queue = new SynchronousQueue(true);
new Thread(()-> {
try {
System.out.println(queue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
queue.put(1);
2 双端阻塞队列
LinkedBlockingDeque: 可以用作工作窃取。
工作窃取(work-stealing)算法是指某个线程从其他队列里窃取任务来执行。
一个大任务分割为若干个互不依赖的子任务,为了减少线程间的竞争,把这些子任务分别放到不同的队列里,并未每个队列创建一个单独的线程来执行队列里的任务,线程和队列一一对应。比如线程1负责处理1队列里的任务,2线程负责2队列的。但是有的线程会先把自己队列里的任务干完,而其他线程对应的队列里还有任务待处理。干完活的线程与其等着,不如帮其他线程干活,于是它就去其他线程的队列里窃取一个任务来执行。而在这时它们可能会访问同一个队列,所以为了减少窃取任务线程和被窃取任务线程之间的竞争,通常会使用双端队列,被窃取任务线程永远从双端队列的头部拿任务执行,而窃取任务线程永远从双端队列的尾部拿任务执行。
如Java中的fork/join模型就是利用了工作窃取来实现的。
3 单端非阻塞队列:
其实现是 ConcurrentLinkedQueue。
4 双端非阻塞队列:
其实现是 ConcurrentLinkedDeque。