10_阻塞队列

Posted root_zhb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了10_阻塞队列相关的知识,希望对你有一定的参考价值。

1、概述

  1. 当队列是空的,从队列中获取元素的操作将会被阻塞。
  2. 当队列是满的,向队列中添加元素的操作将会被阻塞。
  3. 试图从空的队列中获取元素的线程将会被阻塞,直到其他线程往空的队列插入新的元素
  4. 试图向已满的队列中添加新元素的线程将会被阻塞,直到其他线程从队列中移除一个或多个元素或者完全清空,使队列变得空闲起来并后续新增

2、架构

3、分类

  1. ArrayBlockingQueue: 由数组结构组成的有界阻塞队列。
  2. LinkedBlockingQueue:由链表结构组成的有界(但大小默认值为Integer.MAX_VALUE)阻塞队列。
  3. DelayQueue:使用优先级队列实现的延迟无界阻塞队列。
  4. PriorityBlockingQueue::支持优先级排序的无界阻塞队列。
  5. SynchronousQueue:不存储元素的阻塞队列,也即单个元素的队列。
  6. LinkedTransferQueue:由链表组成的无界阻塞队列。
  7. LinkedBlockingDeque:由链表组成的双向阻塞队列。

ArrayBlockingQueue 和 LinkedBlockingQueue 是两个最普通也是最常用的阻塞队列,一般情况下,在处理多线程间的生产者消费者问题,使用这两个类足以。

4、核心方法

Throws exceptionSpecial valueBlocksTimes out
Insertadd(e)add(e)put(e)offer(e, time, unit)
Removeremove()poll()take()poll(time, unit)
Examineelement()peek()not applicablenot applicable
  1. 抛出异常
    当阻塞队列满时,再往队列里 add 插入元素会抛出 IllegalStateException:Queue full
    当阻塞队列空时,再往队列里 remove 移除元素会抛出 NoSuchElementException
  2. 特殊值
    插入方法,成功 true 失败 false
    移除方法,成功返回出队列的元素,队列里没有就返回 null
  3. 一直阻塞
    当阻塞队列满时,生产者线程继续往队列里 put 元素,队列会一直阻塞生产者线程直到 put 数据 or 响应中断退出
    当阻塞队列空时,消费者线程试图从队列 take 元素,队列会一直阻塞消费者线程直至队列可用
  4. 超时退出
    当阻塞队列满时,队列会阻塞生产者线程一定时间,超过限时后生产者线程会退出
public class BlockingQueueDemo {
    public static void main(String[] args) throws InterruptedException {
// List list = new ArrayList();
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
//第一组
//     System.out.println(blockingQueue.add("a"));
//     System.out.println(blockingQueue.add("b"));
//     System.out.println(blockingQueue.add("c"));
//     System.out.println(blockingQueue.element());
//    System.out.println(blockingQueue.add("x"));
//     System.out.println(blockingQueue.remove());
//     System.out.println(blockingQueue.remove());
//     System.out.println(blockingQueue.remove());
//     System.out.println(blockingQueue.remove());
// 第二组
//     System.out.println(blockingQueue.offer("a"));
//     System.out.println(blockingQueue.offer("b"));
//     System.out.println(blockingQueue.offer("c"));
//     System.out.println(blockingQueue.offer("x"));
//     System.out.println(blockingQueue.poll());
//     System.out.println(blockingQueue.poll());
//     System.out.println(blockingQueue.poll());
//     System.out.println(blockingQueue.poll());
// 第三组
//         blockingQueue.put("a");
//         blockingQueue.put("b");
//         blockingQueue.put("c");
         blockingQueue.put("x");
//         System.out.println(blockingQueue.take());
//         System.out.println(blockingQueue.take());
//         System.out.println(blockingQueue.take());
//         System.out.println(blockingQueue.take());
    // 第四组
        System.out.println(blockingQueue.offer("a"));
        System.out.println(blockingQueue.offer("b"));
        System.out.println(blockingQueue.offer("c"));
        System.out.println(blockingQueue.offer("a",3L, TimeUnit.SECONDS));
    }
}

5、总结

  1. 在多线程领域:所谓阻塞,在某些情况下会挂起线程(即阻塞),一旦条件满足,被挂起的线程又会自动被唤起。
  2. 为什么需要 BlockingQueue?
    在 concurrent 包发布以前,在多线程环境下,我们每个程序员都必须去自己控制这些细节,尤其还要兼顾效率和线程安全,而这会给我们的程序带来不小的复杂度。使用后我们不需要关心什么时候需要阻塞线程,什么时候需要唤醒线程,因为这一切 BlockingQueue 都包办了

以上是关于10_阻塞队列的主要内容,如果未能解决你的问题,请参考以下文章

# Java 常用代码片段

JUC高级多线程_07:读写锁与阻塞队列的具体介绍与使用

调度队列时应用程序阻塞

Java多线程_阻塞队列

16_Queue_利用wait()和notify()编写一个阻塞队列

并发_006 容器 队列