了解阻塞队列BlockingQueue和简单的API

简介: 了解阻塞队列BlockingQueue和简单的API

了解阻塞队列BlockingQueue


队列的特性:FIFO(先进先出)

其实就是写入和读取两个操作  写入和读取会有以下情况(不得不阻塞)

写入:如果队列满了,就必须阻塞等待(如果队列满了,就要阻塞等待,等其他队列出来了再进行写入操作)

读取:如果队列是空的,必须阻塞等待生产(读不到数据,需要先写入在进行读取)

阻塞队列:BlockingQueue 它其实是一个JUC下的接口并且和list,set同级,父类collection,实现类ArrayBlockingQueue(以数组实现的阻塞队列),LinkedBlockingQueue(以链表实现的阻塞队列),SynchronousQueue(同步队列)

它不是一个新的东西,和set,list同一级,都是collction下的接口,是一种更厉害的数据结构,它和Queue(队列,)是平级的,并且继承了Queue(队列,实现类有一个Deque(双端队列,也就是可以从左到右,从右到左执行,更加灵活多变),还有一个AbstractQueue(非阻塞队列),还有就是BlockingQueue(阻塞队列)),

使用场景:线程池和多线程并发处

队列家族关系图如下所示

image.png


以上就是一些概念,下面就开始写代码使用队列

其实和list,set一样主要就两个操作,添加 删除

但是根据不同的情况分为4组不同的API

  1. 抛出异常
  2. 不会抛出异常
  3. 阻塞等待
  4. 超时等待

方式

抛出异常

不会抛出异常,有返回值

阻塞等待(一直等待)

超时等待(规定时间内等待)

添加

add

offer

put()

offer(E e, long timeout, TimeUnit unit)

删除(移除)

remove

poll

take()

pollt(long timeout, TimeUnit unit)

检测队首(第一个进入队列的)元素

element

peek

阻塞不存在检测

阻塞不存在检测


创建阻塞队列

通过源码发现阻塞队列有一个重写方法,参数为队列初始大小(必须填写),是否公平(默认是不公平,可以不写,如果为true则为公平)


//创建BlockingQueue的实现类ArrayBlockingQueue(一个数组形的阻塞队列) 
//第一个参数不是泛型 而是队列的大小(可以存放多少个元素)
//第二个参数表示是否公平,默认是不公平的,一般可以不用去指名
ArrayBlockingQueue arrayBlockingQueue=new ArrayBlockingQueue<>(5,false);


image.png


public ArrayBlockingQueue(int capacity) {
this(capacity, false);
}
public ArrayBlockingQueue(int capacity, boolean fair) {
if (capacity <= 0)
throw new IllegalArgumentException();
this.items = new Object[capacity];
lock = new ReentrantLock(fair);
notEmpty = lock.newCondition();
notFull =  lock.newCondition();
}


1 第一组(抛出异常) add remove

如果操作不成功则会抛出异常


//创建BlockingQueue的实现类ArrayBlockingQueue(一个数组形的阻塞队列) 
//第一个参数不是泛型 而是队列的大小(可以存放多少个元素)
//第二个参数表示是否公平,默认是不公平的,一般可以不用去指名
ArrayBlockingQueue arrayBlockingQueue=new ArrayBlockingQueue<>(5,false);
//添加 参数为添加的元素 返回类型为布尔值 成功返回true 不成功返回false
arrayBlockingQueue.add(1);
//移除
arrayBlockingQueue.remove()
//查看队首
arrayBlockingQueue.element()


添加:add()    

关于add查看源码发现,需要一个Object类型的参数,返回一个boolan值(true或false),成功为true,失败为false

package com.wyh.BlockingQueue;
import java.util.concurrent.ArrayBlockingQueue;
/**
 * @program: JUC
 * @description: JUC下的阻塞队列demo
 * @author: 魏一鹤
 * @createDate: 2022-02-20 19:45
 **/
public class BlockingQueueDemo1 {
public static void main(String[] args){
   //创建BlockingQueue的实现类ArrayBlockingQueue(一个数组形的阻塞队列)
        //第一个参数不是泛型 而是队列的大小(可以存放多少个元素)
        //第二个参数表示是否公平,默认是不公平的,一般可以不用去指名
        ArrayBlockingQueue arrayBlockingQueue=new ArrayBlockingQueue<>(5);
        //add添加方法 需要一个object型的参数 返回一个布尔值(成功为true,失败为false)
 //如果我们往队列里面添加元素的个数大于了创建队列的时候参数的大小,则会报错
//java.lang.IllegalStateException: Queue full)
 System.out.println(arrayBlockingQueue.add(1));
        System.out.println(arrayBlockingQueue.add(2));
        System.out.println(arrayBlockingQueue.add(3));
    }
}


true

true

true


注意:如果我们往队列里面添加元素的个数大于了创建队列的时候参数的大小,则会报错



package com.wyh.BlockingQueue;
import java.util.concurrent.ArrayBlockingQueue;
/**
 * @program: JUC
 * @description: JUC下的阻塞队列demo
 * @author: 魏一鹤
 * @createDate: 2022-02-20 19:45
 **/
public class BlockingQueueDemo1 {
public static void main(String[] args){
//创建BlockingQueue的实现类ArrayBlockingQueue(一个数组形的阻塞队列)
        //第一个参数不是泛型 而是队列的大小(可以存放多少个元素)
        //第二个参数表示是否公平,默认是不公平的,一般可以不用去指名
        ArrayBlockingQueue arrayBlockingQueue=new ArrayBlockingQueue<>(5);
//add添加方法 需要一个object型的参数 返回一个布尔值(成功为true,失败为false)
        //如果我们往队列里面添加元素的个数大于了创建队列的时候参数的大小,则会报错
//java.lang.IllegalStateException: Queue full)
        System.out.println(arrayBlockingQueue.add(1));
        System.out.println(arrayBlockingQueue.add(2));
        System.out.println(arrayBlockingQueue.add(3));
        System.out.println(arrayBlockingQueue.add(4));
        System.out.println(arrayBlockingQueue.add(5));
        System.out.println(arrayBlockingQueue.add(6));
    }
}


package com.wyh.BlockingQueue;
import java.util.concurrent.ArrayBlockingQueue;
/**
 * @program: JUC
 * @description: JUC下的阻塞队列demo四组API 第一组抛出异常
 * @author: 魏一鹤
 * @createDate: 2022-02-20 19:45
 **/
//阻塞队列四组API:第一组抛出异常
public class BlockingQueueDemo1 {
public static void main(String[] args){
test1();
    }
public static void test1(){
//创建BlockingQueue的实现类ArrayBlockingQueue(一个数组形的阻塞队列)
        //第一个参数不是泛型 而是队列的大小(可以存放多少个元素)
        //第二个参数表示是否公平,默认是不公平的,一般可以不用去指名
        ArrayBlockingQueue arrayBlockingQueue=new ArrayBlockingQueue<>(3);
//add添加方法 需要一个object型的参数 返回一个布尔值(成功为true,失败为false)
        //如果我们往队列里面添加元素的个数大于了创建队列的时候参数的大小,队列已经满了还要添加,则会报错
        //java.lang.IllegalStateException: Queue full) 队列已满
        System.out.println(arrayBlockingQueue.add(1));
        System.out.println(arrayBlockingQueue.add(2));
        System.out.println(arrayBlockingQueue.add(3));
//循环打印下标 使用 for i 循环
        for (int i = 0; i < arrayBlockingQueue.size(); i++)
            System.out.println(i);
//循环打印arrayBlockingQueue中的元素 使用foreach循环
        for (Object o : arrayBlockingQueue) {
            System.out.println(o);
        }
    }
}


true

true

true

0

1

2

1

2

3


删除:remove()  

    remove方法没有参数,返回类类型是一个E,E就是它弹出来的那个元素,它是一个往外弹的过程,遵循FIFO(先进先出),如果进入先后顺序是1,2,3那么出去先后顺序也是1,2,3


package com.wyh.BlockingQueue;
import java.util.concurrent.ArrayBlockingQueue;
/**
 * @program: JUC
 * @description: JUC下的阻塞队列demo四组API 第一组抛出异常
 * @author: 魏一鹤
 * @createDate: 2022-02-20 19:45
 **/
public class BlockingQueueDemo1 {
public static void main(String[] args){
test1();
    }
    //第一组 抛出异常
public static void test1(){
//创建BlockingQueue的实现类ArrayBlockingQueue(一个数组形的阻塞队列)
        //第一个参数不是泛型 而是队列的大小(可以存放多少个元素)
        //第二个参数表示是否公平,默认是不公平的,一般可以不用去指名
        ArrayBlockingQueue arrayBlockingQueue=new ArrayBlockingQueue<>(3);
//add添加方法 需要一个object型的参数 返回一个布尔值(成功为true,失败为false)
        //如果队列已经满了还要添加,则会报错
        //java.lang.IllegalStateException: Queue full) 队列已满 抛出异常
        System.out.println(arrayBlockingQueue.add(1));
        System.out.println(arrayBlockingQueue.add(2));
        System.out.println(arrayBlockingQueue.add(3));
//分隔符 方便观看
        System.out.println("-------------------------------");
 //根据FIFO先进先出规格 弹出先进去的三个元素
        System.out.println(arrayBlockingQueue.remove()); 
        System.out.println(arrayBlockingQueue.remove());
        System.out.println(arrayBlockingQueue.remove());
    }
}
目录
相关文章
|
机器学习/深度学习 存储 数据采集
数据分析案例-基于多元线性回归算法预测学生期末成绩
数据分析案例-基于多元线性回归算法预测学生期末成绩
1807 0
数据分析案例-基于多元线性回归算法预测学生期末成绩
|
11月前
|
存储 SQL 缓存
优化ClickHouse查询性能:最佳实践与调优技巧
【10月更文挑战第26天】在大数据分析领域,ClickHouse 以其卓越的查询性能和高效的列式存储机制受到了广泛的关注。作为一名已经有一定 ClickHouse 使用经验的开发者,我深知在实际应用中,合理的表设计、索引优化以及查询优化对于提升 ClickHouse 性能的重要性。本文将结合我的实践经验,分享一些有效的优化策略。
1220 3
|
Cloud Native 测试技术 开发者
阿里云服务网格ASM多集群实践(二):高效按需的应用多环境部署与全链路灰度发布
介绍服务网格ASM提出的一种多集群部署下的多环境部署与全链路灰度发布解决方案。
|
存储 算法 安全
程序员必知:分布式一致性Raft与JRaft
程序员必知:分布式一致性Raft与JRaft
239 0
|
存储 安全 Java
20个SpringSecurity框架核心组件源码详解
以上是 V 哥给大家整理的20个Spring Security 中核心组件的分析与运行过程,理解后可助你玩转Spring Security,如果文章对你有帮助,客官请点赞收藏转发给更多需要的兄弟,任何疑问请评论区与V哥交流。
188 0
|
SQL 存储 消息中间件
海量数据存储Sharding-JDBC分库分表3
海量数据存储Sharding-JDBC分库分表
|
Android开发 芯片
【Android篇】MTK平台编译流程
MTK是联发科技的缩写,是一家面向全球的半导体芯片厂商。如果你要编译MTK Android代码,可以按如下步骤进行: 1配置环境变量 在.终端输入以下命令,将编译所需的工具链路径加入环境变量中。
966 0
|
监控 安全 机器人
Hunter狩猎者夹子机器人系统开发丨现成案例
区块链系统由无数节点构成,这些节点类似于一台tai.独立工作的计算机,当需要记账的时候,每一个节点都会参与竞争,系统会在一段时间内选出合适的节点来记账,而这个节点就会在数据区块中记录下近期发生的数据变化,记录完成后,节点就会把这个数据区块发送给其他节点,其他节点首先会核实数据,数据无误的话,就会把这个数据区块也放入自己的账本当中,于是系统里的所有节点都拥有一个完全一样的数据区块,即账本。 这种记账方式被称为区块链技术或者分布式总账技术
Hunter狩猎者夹子机器人系统开发丨现成案例
Lniux关于虚拟内存的错误
Lniux关于虚拟内存的错误
202 0
Lniux关于虚拟内存的错误