教你一文了解阻塞队列(资源存放地-JUC)

1.简介

阻塞队列 BlockingQueue:阻塞即线程想要获取资源却没有资源的现象,队列即先进先出数据结构 ,是生产者存放元素的容器,而消费者也只从容器里拿元素。
在这里插入图片描述

  • 当阻塞队列为空时,从队列中获取元素的Thread1操作将会被阻塞
  • 当阻塞队列为满时,从队列中添加元素的Thread2操作将会被阻塞

2.场景

餐饮店餐位被占满后,此时如果还有客人到来,餐饮店应该让后来的这些客人去等待区等待,不能粗暴通知他们无座,然后抛弃他们。

  • 此时可使用的餐位数就相当于阻塞队列内部的可获取元素个数,当餐位无空余时,想要获取餐位的客人,将会被阻塞。
  • 有客人就餐完毕,就相当于往阻塞队列中添加元素,但因为总餐位的限制,当阻塞队列中的餐位达到餐饮店总餐位时,也不会再插入可获取的餐位

3.阻塞队列的好处

我们不再需要关心什么时候需要去阻塞线程,什么时候需要去唤醒线程,全部交给BlockingQueue来判断。

  • 只要BlockingQueue中的元素为空,则消费者线程被阻塞,当生产者线程执行时,该生产者线程唤醒所有消费者线程
  • 只要BlockingQueue中的元素为满,则生产者线程被阻塞,当消费者线程执行时,该消费者线程唤醒所有生产者线程

3-1.阻塞队列的组织架构

在这里插入图片描述

3-2.线程池的底层为下图中标红的三个结构

在这里插入图片描述

3-3.各种阻塞队列中共有的核心方法如下图(其他方法很少使用到)

在这里插入图片描述
将加入、移除、检查按照错误处理的方式分成四组api调用:

  • 抛出异常组:是指当阻塞队列满时候,再往队列里插入元素,会抛出 IllegalStateException(“Queue full”) 异常。当队列为空时,从队列里获取元素时会抛出 NoSuchElementException 异常 。

  • 返回特殊值组:插入方法会返回是否成功,成功则返回 true。移除方法,则是从队列里拿出一个元素,如果没有则返回 null

  • 一直阻塞组:当阻塞队列满时,如果生产者线程往队列里 put 元素,队列会一直阻塞生产者线程,直到拿到数据,或者响应中断退出。当队列空时,消费者线程试图从队列里 take 元素,队列也会阻塞消费者线程,直到队列可用。(消息中间件使用较多,因为消息不能因为阻塞而丢失)- 谚语:死战不退

  • 超时退出组:当阻塞队列满时,队列会阻塞生产者线程一段时间,如果超过一定的时间,生产者线程就会退出,并且返回插入结果,成功返回true。api参数中e为插入元素,time为时间数,unit为time的单位(TimeUnit.SECONDS)。- 谚语:过时不候

4.核心方法代码演示(抛出异常组-相对暴力)

4-1.add添加元素方法(无异常添加元素代码 和 有异常添加元素代码)

无异常添加演示:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class BlockingQueueDemo {
    public static void main(String[] args) {
        // 创建一个只有3个位置可用的阻塞队列
        // 上下对比:List list = new ArrayList(3)
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
        // 输出添加结果boolean值
        System.out.println(blockingQueue.add("a"));
        System.out.println(blockingQueue.add("b"));
        System.out.println(blockingQueue.add("c"));
    }
}

在这里插入图片描述
4-1-2.有异常添加演示:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class BlockingQueueDemo {
    public static void main(String[] args) {
        // 创建一个只有3个位置可用的阻塞队列
        // 上下对比:List list = new ArrayList(3)
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);       
        // 输出添加结果boolean值
        System.out.println(blockingQueue.add("a"));
        System.out.println(blockingQueue.add("b"));
        System.out.println(blockingQueue.add("c"));
        System.out.println(blockingQueue.add("d"));
    }
}

抛出了队列满溢异常:
在这里插入图片描述

4-2.remove移除队头元素方法(无异常移除元素代码 和 有异常移除元素代码)

4-2-1.无异常移除队头元素元素演示:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class BlockingQueueDemo {
    public static void main(String[] args) {
        // 创建一个只有3个位置可用的阻塞队列
        // 上下对比:List list = new ArrayList(3)
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
        // 输出添加boolean值
        System.out.println("开始添加");
        System.out.println(blockingQueue.add("a"));
        System.out.println(blockingQueue.add("b"));
        System.out.println(blockingQueue.add("c"));
        // 输出移除元素boolean值
        System.out.println("开始移除");
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
    }
}

在这里插入图片描述

4-2-1.有异常移除队头元素元素演示:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class BlockingQueueDemo {
    public static void main(String[] args) {
        // 创建一个只有3个位置可用的阻塞队列
        // 上下对比:List list = new ArrayList(3)
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
        // 输出添加boolean值
        System.out.println("开始添加");
        System.out.println(blockingQueue.add("a"));
        System.out.println(blockingQueue.add("b"));
        System.out.println(blockingQueue.add("c"));
        // 输出移除元素boolean值
        System.out.println("开始移除");
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
    }
}

在这里插入图片描述

4-3.elemet获取队头元素(FIFO)方法

4-3-1.获取队头元素演示(可用于检查队是否有可用元素):

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class BlockingQueueDemo {
    public static void main(String[] args) {
        // 创建一个只有3个位置可用的阻塞队列
        // 上下对比:List list = new ArrayList(3)
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
        // 输出添加boolean值
        System.out.println("开始添加");
        System.out.println(blockingQueue.add("a"));
        System.out.println(blockingQueue.add("b"));
        System.out.println(blockingQueue.add("c"));
        System.out.println("对头元素: " + blockingQueue.element());
        // 输出移除元素boolean值
        System.out.println("开始移除");
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
    }
}

在这里插入图片描述

5.核心方法代码演示(返回boolean组-相对温和)

5-1.offer添加元素方法(正确添加元素代码 和 错误添加元素代码)

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class BlockingQueueDemo {
    public static void main(String[] args) {
        // 创建一个只有3个位置可用的阻塞队列
        // 上下对比:List list = new ArrayList(3)
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
        // 输出添加boolean值
        System.out.println("开始添加");
        System.out.println(blockingQueue.offer("a"));
        System.out.println(blockingQueue.offer("b"));
        System.out.println(blockingQueue.offer("c"));
        System.out.println(blockingQueue.offer("c"));
    }
}

在这里插入图片描述

5-2.poll移除元素方法(正确移除元素代码 和 错误移除元素代码)

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class BlockingQueueDemo {
    public static void main(String[] args) {
        // 创建一个只有3个位置可用的阻塞队列
        // 上下对比:List list = new ArrayList(3)
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
        // 输出添加boolean值
        System.out.println("开始添加");
        System.out.println(blockingQueue.offer("a"));
        System.out.println(blockingQueue.offer("b"));
        System.out.println(blockingQueue.offer("c"));
        // 输出移除元素boolean值
        System.out.println("开始移除");
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值