请见:https://juejin.im/entry/5b39bc776fb9a00e5c5f9407、https://juejin.im/post/5a093ff551882531bb6c4ee3#heading-12
java.util.concurrent Java 并发工具包是 Java5 添加的一个并发工具包。这个包包含了一系列能够让 Java 的并发编程变得更加简单轻松的类。
JUC中有非常多的类,将部分类按功能进行分类,分别是:
- 之前提到过的原子atomic包
- 比synchronized功能更强大的lock包
- 线程调度管理工具
- 线程安全与并发工具集合
- 线程池
1. 阻塞队列 BlockingQueue
使用场景:通常用于一个线程生产对象,而另一个线程消费这些对象
生产:一个线程将会持续生产新对象并将其插入到队列之中,直到队列达到它所能容纳的临界点。也就是说,它是有限的。如果该阻塞队列到达了其临界点,负责生产的线程将会在往里面插入新对象时发生阻塞。它会一直处于阻塞之中,直到负责消费的线程从队列中拿走一个对象。负责消费的线程将会一直从该阻塞队列中拿出对象。
消费:如果消费线程尝试去从一个空的队列中提取对象的话,这个消费线程将会处于阻塞之中,直到一个生产线程把一个对象丢进队列。
1.1 BlockingQueue 的方法
BlockingQueue 具有4组不同的方法用于插入、移除以及对队列中的元素进行检查。
四组不同的行为方式解释:
- 抛异常:如果试图的操作无法立即执行,抛一个异常(例如:add时,队列已满、remove时,队列为空)
- 特定值:如果试图的操作无法立即执行,返回一个特定的值(一般是 true/false)
- 阻塞:如果试图的操作无法立即执行,该方法将会发生阻塞,直到能执行
- 超时:如果试图的操作无法立即执行,该方法调用将会发生阻塞,直到能够执行,但等待时间不会超过给定值。返回一个特定的值以告知该操作是否成功。
1.2 BlockingQueue 的实现
1.2.1 ArrayBlockingQueue-数组队列
ArrayBlockingQueue 是一个有界的阻塞队列,其内部实现是将对象放到一个object数组里。可以在对其初始化的时候设定队列存储的上限,之后就无法对这个上限进行修改了,因为是 final Object[] items 。
ArrayBlockingQueue 内部以 FIFO(先进先出)的顺序对元素进行存储。队列中的头元素在所有元素之中是放入时间最久的那个,而尾元素则是最短的那个。
1.2.2 DelayQueue-延迟队列
DelayQueue中每个元素有一个延迟时间,可以通过元素的getDelay()方法获取,等到该延迟时间过期之后,该元素才能被释放,将会在 DelayQueue 的下一次 take 被调用的时候被释放掉。
注入其中的元素必须实现 concurrent.Delay 接口,该接口定义:
public interface Delayed extends Comparable<Delayed> {
long getDelay(TimeUnit var1);
}
传递给 getDelay 方法的 getDelay 实例是一个枚举型,它表明了将要延迟的时间段。
1.2.3 LinkedBlockingQueue-链阻塞队列
LinkedBlockingQueue 内部以一个链式结构对其元素进行存储。如果需要的话,这一链式结构可以选择一个上线。如果没有定义上限,将使用 Ingeter.MAX_VALUE 作为上限。
LinkedBlockingQueue 内部以 FIFO(先进先出)的顺序对元素进行存储。队列中的头元素在所有元素之中是放入时间最久的那个。
1.2.4 PriorityBlockingQueue-优先级阻塞队列
PriorityBlockingQueue 是一个无界的并发队列。它使用了和 PriorityQueue 一样的排序规则。你无法向这个队列中插入 null 值。
所有插入到 PriorityBlockingQueue 的元素必须实现 Comparable 接口或者在构造方法中传入Comparator。
注意:PriorityBlockingQueue 对于具有相等优先级的元素并不强制任何特定的行为。
同时注意:如果你从一个 PriorityBlockingQueue 获得一个 Iterator 的话,该 Iterator并不能保证它对元素的遍历是按照优先顺序的。原理在之前的文章中分析过~
1.2.5 SynchronousQueue-同步队列
SynchronousQueue 是一个特殊的队列,内部同时只能容纳单个元素。如果该队列已有一个元素的话,试图向队列中插入一个新元素的线程将会阻塞,知道另一个线程将该元素从队列中抽走。同样,如果该队列为空,试图向队列中抽取一个元素的线程将会阻塞,直到另一个线程向队列中插入了一条新的元素。
据此,把这个类称作一个队列显然是夸大其词,它更多像是一个汇合点。
使用方法和 ArrayBlockingQueue 一样吧,区别就是 SynchronousQueue 只能保存一个元素。
2. ConcurrentMap-并发 Map
2.1 ConcurrentHashMap