突击并发编程JUC系列-阻塞队列 BlockingQueue( 二 )

LinkedBlockingQueueLinkedBlockingQueue 是一个用链表实现的有界阻塞队列 。 此队列的默认和最大长度为 Integer.MAX_VALUE。 此队列按照先进先出的原则对元素进行排序 。
PriorityBlockingQueuePriorityBlockingQueue 是一个支持优先级的无界阻塞队列 。 默认情况下元素采取自然顺序升序排列 。 也可以自定义类实现 compareTo() 方法来指定元素排序规则 , 或者初始化 PriorityBlockingQueue 时 , 指定构造参数Comparator 来对元素进行排序 。 需要注意的是不能保证同优先级元素的顺序 。
public class PriorityBlockingQueueExample1 {public static void main(String[] args) {PriorityBlockingQueue queue = new PriorityBlockingQueue();queue.offer(1);queue.offer(12);queue.offer(21);queue.offer(6);// 内部排序System.out.println(queue.poll()); // 1System.out.println(queue.poll()); // 6System.out.println(queue.poll()); // 12System.out.println(queue.poll()); //21}}DelayQueueDelayQueue 是一个支持延时获取元素的无界阻塞队列 。 队列使用 PriorityQueue 来实现 。 队列中的元素必须实现 Delayed 接口 , 在创建元素时可以指定多久才能从队列中获取当前元素 。 只有在延迟期满时才能从队列中提取元素 。
DelayQueue 非常有用 , 可以将 DelayQueue 运用在以下应用场景 。

  • 缓存系统的设计:可以用 DelayQueue 保存缓存元素的有效期 , 使用一个线程循环查询 DelayQueue, 一旦能从 DelayQueue 中获取元素时 , 表示缓存有效期到了 。
  • 定时任务调度:使用 DelayQueue 保存当天将会执行的任务和执行时间 , 一旦从 DelayQueue 中获取到任务就开始执行 , 比如 TimerQueue 就是使用 DelayQueue 实现的 。
DelayQueue 队列的元素必须实现 Delayed 接口 。 我们可以参考 ScheduledThreadPoolExecutor 里 ScheduledFutureTask 类的实现 。
public class DelayQueueExample1 {public static void main(String[] args) throws InterruptedException {DelayQueue queue = new DelayQueue<>();// 延期3秒 处理queue.put(new DelayedEntry("A", 30000L));// 延期10 秒处理queue.add(new DelayedEntry("B", 10000L));// 延期 20 秒处理queue.add(new DelayedEntry("C", 20000L));int size = queue.size();System.out.println("当前时间是:" + LocalDateTime.now());// 从延时队列中获取元素 ,将输出 A , B , Cfor (int i = 0; i < size; i++) {System.out.println(queue.take() + " ------ " + LocalDateTime.now());}}}/** * 继承 Delayed 接口 */class DelayedEntry implements Delayed {/*** 元素数据内容*/private final String value;/*** 用于计算失效时间*/private final long exeTime;DelayedEntry(String value, long exeTime) {this.value = http://kandian.youth.cn/index/value;this.exeTime = exeTime + System.currentTimeMillis();}@Overridepublic long getDelay(TimeUnit unit) {return exeTime - System.currentTimeMillis();}@Overridepublic int compareTo(Delayed o) {DelayedEntry t = (DelayedEntry) o;if (this.exeTime < t.exeTime) {return -1;} else if (this.exeTime> t.exeTime) {return 1;} else {return 0;}}@Overridepublic String toString() {return "DelayedEntry{" +"value="http://kandian.youth.cn/index/+ value +", exeTime=" + exeTime +'}';}}//当前时间是:2020-10-15T16:26:37.167//DelayedEntry{value=http://kandian.youth.cn/index/B, exeTime=1602750407104} ------ 2020-10-15T16:26:47.117// DelayedEntry{value=C, exeTime=1602750417104} ------ 2020-10-15T16:26:57.105//DelayedEntry{value=A, exeTime=1602750427104} ------ 2020-10-15T16:27:07.104SynchronousQueueSynchronousQueue 是一个不存储元素的阻塞队列 。 每一个put操作必须等待一个take操作 , 否则不能继续添加元素 。
它支持公平访问队列 。 默认情况下线程采用非公平性策略访问队列 。 使用以下构造方法可以创建公平性访问的 SynchronousQueue, 如果设置为true , 则等待的线程会采用先进先出的顺序访问队列 。
LinkedTransferQueueLinkedTransferQueue 是一个由链表结构组成的无界阻塞 TransferQueue 队列 。 相对于其他阻塞队列 ,LinkedTransferQueue 多了 tryTransfer 和 transfer 方法 。