首页 > 技术文章 > 阻塞队列

lanxinren 2021-04-26 10:28 原文

概念

  • 队列遵循FIFO原则,即first input first output 先进先出原则。

  • 阻塞队列

    1. 写入(put):如果队列满了就必须阻塞等待。
    2. 取(take): 如果队列是空的,就必须阻塞等待生产。
  • 关于BlockingQueueAPI如下

    在这里插入图片描述

  • 阻塞队列 BlockQueue 是Collection 的一个子类(应用场景:多线程并发处理、线程池)

在这里插入图片描述

阻塞队列常用方法

方式 抛出异常 不会抛出异常 阻塞等待 超时等待
添加 add offer put offer(timenum,timeUnit)
移出 remove poll take poll(timenum,timeUnit)
判断队首元素 element peek -

下面的示例通过junit进行单元测试,需要导入如下依赖。

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

示例一 抛出异常的增加和移除方法

@Test
public void test01(){
    //实例化一个长度为3的队列
    ArrayBlockingQueue<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());//a 抛出 队首
    //如果添加第4个及以上元素就会抛出异常 java.lang.IllegalStateException: Queue full
    System.out.println(blockingQueue.remove());//a 取出的时候遵循先进先出
    System.out.println(blockingQueue.remove());
    System.out.println(blockingQueue.remove());
    //如果再移除一个,就会造成 java.util.NoSuchElementException
}
//结果 true true true a a b c

示例二 不抛出异常的增加和移除方法

 @Test
 public void test02(){
     ArrayBlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3)
     System.out.println(blockingQueue.offer("a"));
     System.out.println(blockingQueue.offer("b"));
     System.out.println(blockingQueue.offer("c"));
     //添加第4个元素及以上不会抛出异常,返回false
     System.out.println(blockingQueue.offer("d"));
     System.out.println(blockingQueue.peek());//打印对首元素
     System.out.println(blockingQueue.poll());
     System.out.println(blockingQueue.poll());
     System.out.println(blockingQueue.poll());
     //移除第四个元素及以上不会抛出异常,返回null
     System.out.println(blockingQueue.poll());
 }

//结果:true true true false a a b c null

示例三 阻塞等待(一直等待)

@Test
public void test03() throws InterruptedException {
    ArrayBlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
    blockingQueue.put("a");
    blockingQueue.put("b");
    blockingQueue.put("c");
    //一直阻塞,第4个值不会添加成功
    //blockingQueue.put("c");
    System.out.println(blockingQueue.take());
    System.out.println(blockingQueue.take());
    System.out.println(blockingQueue.take());
    //一直阻塞,取不出第4个值
    //System.out.println(blockingQueue.take());
}

示例4 超时等待(过时不候,超过时间就不等待)

@Test
 public void test04() throws InterruptedException {
     ArrayBlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
     System.out.println(blockingQueue.offer("a"));
     System.out.println(blockingQueue.offer("b"));
     System.out.println(blockingQueue.offer("c"));
     System.out.println("开始等待");
     System.out.println(blockingQueue.offer("d", 2, TimeUnit.SECONDS));
     System.out.println("等待结束");
     System.out.println("=================取值=====================");
     System.out.println(blockingQueue.poll());
     System.out.println(blockingQueue.poll());
     System.out.println(blockingQueue.poll());
     System.out.println("取值开始等待");
     System.out.println(blockingQueue.poll(2, TimeUnit.SECONDS));//超过两秒,我们就不等待了
     System.out.println("取值结束等待");
 }

结果

true
true
true
开始等待
false
等待结束
=================取值=====================
a
b
c
取值开始等待
null
取值结束等待

参考教程:https://www.kuangstudy.com/

下一篇:同步队列

推荐阅读