最近在复习多线程的知识,必然少不了要扫描一遍JUC包下的各个类或接口,今天就先来聊一聊阻塞队列BlockingQueue;

BlockingQueue是jdk1.5发布的JUC包下的一个工具类,他提供了天生阻塞的拿(put)和取(take)元素的方法,线程安全,通过其阻塞的put、take方法能很好的实现生产者消费者模型,解决线程间的通信问题,

下面先分别介绍其本身拥有的一些特性方法和实现类

特性方法

boolean add(E e);        添加元素,成功返回true,失败返回false,如果队列设置了长度,超长会抛java.lang.IllegalStateException: Queue full异常

void put(E e);               阻塞式的添加元素,如果队列超长当前线程会一直阻塞,直到队列里的元素被take可以成功添加为止

boolean offer(E e);       添加元素,成功返回true,失败返回false,与add的区别在于队列满了添加失败不会抛异常而是返回false

E take();                        阻塞式的获取队列元素,只要take不到元素当前线程会一直阻塞,直到队列里有元素并成功获取

E poll();                        从队列头部获取并移除元素,获取不到返回null

E peek();                      从队列头部获取元素但不移除元素,获取不到返回null

int drainTo(Collection<? super E> c);   将队列中的元素全部移除,并发送到给定的集合中,返回的是操作成功的元素个数

特性方法对应的测试用例

/**
* @description: 阻塞队列的常用方法测试
* @author: dll
* @date: Created in 2022/1/6 14:47
* @version:
* @modified By:
*/
public class T08_TestBlockingQueue { public static void main(String[] args) throws InterruptedException {
testDrainTo();
} /**
* 将队列中的元素全部移除,并发送到给定的集合中。
*/
private static void testDrainTo () {
BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
queue.add("1");
queue.add("3");
ArrayList list = new ArrayList();
System.out.println("queue.peek() = " + queue.peek());
int i = queue.drainTo(list);
System.out.println("i = " + i);
System.out.println("list.toString() = " + list.toString());
System.out.println("queue.peek() = " + queue.peek());
} /**
* 从队列头部获取并移除元素,获取不到为null
*/
private static void testPoll() {
BlockingQueue<String> queue = new ArrayBlockingQueue<>(1);
queue.add("123");
System.out.println("queue.poll(1) = " + queue.poll());
System.out.println("queue.remainingCapacity() = " + queue.remainingCapacity());
System.out.println("queue.poll(2) = " + queue.poll());
} /**
* 阻塞式的获取队列元素,只要take不到元素当前线程会一直阻塞,直到队列里有元素并成功获取
*/
private static void testTake() throws InterruptedException {
BlockingQueue<String> queue = new ArrayBlockingQueue<>(1);
new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(5);
queue.add("456");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
queue.put("123");
System.out.println("queue.take() = " + queue.take());
// 此处会阻塞住,直到上面的线程唤醒后往队列添加了元素
System.out.println("queue.take() = " + queue.take());
} /**
* 添加元素,成功返回true,失败返回false,如果队列设置了长度,超长会抛java.lang.IllegalStateException: Queue full异常
* 参数不能为null
*/
private static void testAdd() {
BlockingQueue<String> queue = new ArrayBlockingQueue<>(1);
System.out.println("queue.offer() = " + queue.add("123"));
System.out.println("queue.offer() = " + queue.add("123"));
} /**
* 添加元素,成功返回true,失败返回false,与add的区别在于队列满了添加失败不会抛异常而是返回false
* 参数不能为null
*/
private static void testOffer() {
BlockingQueue<String> queue = new ArrayBlockingQueue<>(1);
System.out.println("queue.offer() = " + queue.offer("123"));
System.out.println("queue.offer() = " + queue.offer("123"));
} /**
* 测试put方法的阻塞式添加
* 阻塞式的添加元素,如果队列超长当前线程会一直阻塞,直到队列里的元素被take可以成功添加为止
* 参数不能为null
* @throws InterruptedException
*/
private static void testPut() throws InterruptedException {
BlockingQueue<String> queue = new ArrayBlockingQueue<>(1);
new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(5);
// 此处用peek下面的put方法仍会阻塞,因为peek只是拿出元素并不会将元素从队列移除
System.out.println("线程里获取到的元素:" + queue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
System.out.println("queue.add() = " + queue.add("1"));
// 此处调用会阻塞当前线程,直至上面的线程被唤醒从队列里拿走一个元素
queue.put("12");
System.out.println("主线程里take的元素:" + queue.take());
} }

关于实现类我也不想利用文本的方式一个个列起来了,下面直接附上我整理的思维导图的部分截图,简单明了:

需要注意的是,BlockingQueue的一众实现类是线程池接收任务队列的多种实现,不同的队列应用于不同场景下的线程池;后面会抽时间写一篇关于线程池的总结笔记

最新文章

  1. 尽量使用translate而不是改变top/left进行动画(翻译)
  2. 360wifi使用方法|360wifi使用教程
  3. 几个最常用的git命令
  4. 从视频文件中读入数据--&gt;将数据转换为灰度图--&gt;对图像做canny边缘检测--&gt;将这三个结构显示在一个图像中
  5. 【BZOJ 1103】 [POI2007]大都市meg
  6. 为clang添加中文关键字
  7. apache压力测试工具的apache bench和JMeter的安装
  8. PAT1022.:Digital Library
  9. [Swift]LeetCode1028. 从先序遍历还原二叉树 | Recover a Tree From Preorder Traversal
  10. Shell 字符串处理
  11. 【洛谷P2257】YY的GCD
  12. Content Security Policy介绍
  13. Shape流动效果
  14. Spring Boot 在IDEA中debug时的hot deployment(热部署)
  15. Spring中IOC与DI的的区别
  16. nginx: [error] open() &quot;/usr/local/var/run/nginx.pid&quot; failed (2: No such file or directory)
  17. PHP 表单 - 4(验证邮件和URL)
  18. 【Linux】忘记root密码
  19. atitit.自动生成数据库结构脚本,或者更换数据库,基于hibernate4
  20. hadoop2.7.2集群搭建

热门文章

  1. C#基础_变量的命名规则
  2. scp复制发送文件夹到其他服务器上
  3. Linux之LVM逻辑卷管理
  4. Android平台摄像头/屏幕/外部数据采集及RTMP推送接口设计描述
  5. QT学习(五)----360界面制作(2终结)
  6. 0.web理解
  7. kubernetes中部署kube-prometheus项目解决ControllerManager与Scheduler无法监控问题
  8. PostgreSQL 创建表格
  9. 3_Nginx
  10. overflow 隐藏滚动条样式