了解阻塞队列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());
    }
}
目录
相关文章
|
6月前
|
存储 安全 算法
解读 Java 并发队列 BlockingQueue
解读 Java 并发队列 BlockingQueue
60 0
|
存储 安全 Java
BlockingQueue(阻塞队列)基本使用指南
BlockingQueue(阻塞队列)基本使用指南
163 1
|
3月前
|
Java API
JUC(5)BlockingQueue四组API
这篇文章介绍了Java中的读写锁ReadWriteLock和阻塞队列BlockingQueue的概念、使用场景以及它们的四种API操作方式:抛出异常、不抛出异常、阻塞等待和超时等待。
JUC(5)BlockingQueue四组API
|
20天前
|
消息中间件 缓存 安全
Future与FutureTask源码解析,接口阻塞问题及解决方案
【11月更文挑战第5天】在Java开发中,多线程编程是提高系统并发性能和资源利用率的重要手段。然而,多线程编程也带来了诸如线程安全、死锁、接口阻塞等一系列复杂问题。本文将深度剖析多线程优化技巧、Future与FutureTask的源码、接口阻塞问题及解决方案,并通过具体业务场景和Java代码示例进行实战演示。
39 3
|
6月前
并发编程之BlockingQueue(阻塞队列)的详细解析
并发编程之BlockingQueue(阻塞队列)的详细解析
28 0
|
消息中间件
并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue使用场景总结
并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue使用场景总结
56 0
|
存储 Java
JUC基础(二)—— Future接口 及其实现
JUC基础(二)—— Future接口 及其实现
168 1
|
缓存 Java 容器
【JavaEE】多线程之阻塞队列(BlockingQueue)
【JavaEE】多线程之阻塞队列(BlockingQueue)
|
存储 Java 容器
并发编程-23J.U.C组件拓展之阻塞队列BlockingQueue 和 线程池
并发编程-23J.U.C组件拓展之阻塞队列BlockingQueue 和 线程池
67 0
|
存储 监控 安全
《JUC并发编程 - 基础篇》 Callable接口 | 辅助类 | 读写锁 | 阻塞队列 | 线程池 | Stream流 | 分支合并框架(二)
《JUC并发编程 - 基础篇》 Callable接口 | 辅助类 | 读写锁 | 阻塞队列 | 线程池 | Stream流 | 分支合并框架
《JUC并发编程 - 基础篇》 Callable接口 | 辅助类 | 读写锁 | 阻塞队列 | 线程池 | Stream流 | 分支合并框架(二)