阻塞队列

阻塞

队列

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

不得不阻塞的情况

什么情况下会使用阻塞队列:多线程并发处理、线程池

学会使用队列

添加、移除

四组API

方式 抛出异常 不抛出异常,有返回值 阻塞等待 超时等待
添加 add offer put offer(E e, long timeout, TimeUnit unit)
移除 remove poll take poll(long timeout, TimeUnit unit)
检测队首元素 element peek

1、抛出异常

public static void test01(){
//队列是有大小的,创建时要明确该队列最大能有几个元素
BlockingQueue queue = new ArrayBlockingQueue<>(3);
//当你添加的元素超出队列规定的最大元素量时,抛出异常java.lang.IllegalStateException: Queue full
System.out.println(queue.add("A"));
System.out.println(queue.add("B"));
System.out.println(queue.add("C"));
//当你移除的元素超出队列中含有的元素量时,抛出异常java.util.NoSuchElementException
System.out.println(queue.element());
System.out.println(queue.remove());
System.out.println(queue.element());
System.out.println(queue.remove());
System.out.println(queue.element());
System.out.println(queue.remove()); System.out.println(queue.add("D"));
}

2、不抛出异常

public static void test02(){
//队列是有大小的,创建时要明确该队列最大能有几个元素
BlockingQueue queue = new ArrayBlockingQueue<>(3);
//当你添加的元素超出队列规定的最大元素量时,不抛出异常,通过返回的boolean值为false来表明
System.out.println(queue.offer("A"));
System.out.println(queue.offer("B"));
System.out.println(queue.offer("C"));
//当你移除的元素超出队列中含有的元素量时,不抛出异常,返回null来提示队列已经没有元素可以弹出了
System.out.println(queue.peek());
System.out.println(queue.poll());
System.out.println(queue.peek());
System.out.println(queue.poll());
System.out.println(queue.peek());
System.out.println(queue.poll()); System.out.println(queue.offer("D"));
}

3、阻塞等待

    public static void test03() throws InterruptedException {
//队列是有大小的,创建时要明确该队列最大能有几个元素
BlockingQueue queue = new ArrayBlockingQueue<>(3); queue.put("a");
queue.put("b");
queue.put("c");
//当队列被元素占满后再进行添加,会一直阻塞等待,知道该元素加入队列
// queue.put("c");
System.out.println(queue.take());
System.out.println(queue.take());
System.out.println(queue.take());
//当队列中没有元素时还去取,也会一直阻塞等待
// System.out.println(queue.take()); }

4、超时等待

public static void test04() throws Exception{
//队列是有大小的,创建时要明确该队列最大能有几个元素
BlockingQueue queue = new ArrayBlockingQueue<>(3);
System.out.println(queue.offer("a"));
System.out.println(queue.offer("b"));
System.out.println(queue.offer("c"));
//当队列被占满时,设置超时等待,超过两秒就不等了,进不去就不进了
System.out.println(queue.offer("d", 2, TimeUnit.SECONDS));
System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.poll());
//当队列元素为空时,设置超时等待,超过两秒就不等了,拿不到就不拿了
System.out.println(queue.poll(2, TimeUnit.SECONDS));
}

SynchronousQueue

同步队列:同步队列每次插入操作都必须等待另一个线程执行相应的删除操作,反之亦然。同步队列没有容量,也就意味着只有当一个元素弹出后才能再进入一个元素,只能同时有一个元素。

存取:put、take

package org.example.qu;

import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit; public class SynchronousQueueDemo {
public static void main(String[] args) {
SynchronousQueue<String> synchroQueue = new SynchronousQueue<String>(); new Thread(() -> {
try {
//直接在队列中存入三个元素
System.out.println(Thread.currentThread().getName() + ": put 1");
synchroQueue.put("1");
System.out.println(Thread.currentThread().getName() + ": put 2");
synchroQueue.put("2");
System.out.println(Thread.currentThread().getName() + ": put 3");
synchroQueue.put("3"); } catch (InterruptedException e) {
throw new RuntimeException(e);
}
}, "T1").start();
new Thread(() -> {
try {
//每次取之间延迟三秒
TimeUnit.SECONDS.sleep(3);
System.out.println(synchroQueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(synchroQueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(synchroQueue.take()); } catch (InterruptedException e) {
throw new RuntimeException(e);
}
}, "T2").start(); }
}

我们通过结果发现,将要存入的元素会等待已经被存入的元素取出后才会存入,延迟三秒取出时,将要存入的元素也在等待三秒取出后再存入,这就是所谓的同步队列每次插入操作都必须等待另一个线程执行相应的删除操作,反之亦然。

同步队列和其它BlockingQueue不一样,他不存储元素,你put了一个值必须take取出,否则不能再put进去元素。

JUC并发编程学习笔记(九)阻塞队列的更多相关文章

  1. JUC并发编程学习笔记

    JUC并发编程学习笔记 狂神JUC并发编程 总的来说还可以,学到一些新知识,但很多是学过的了,深入的部分不多. 线程与进程 进程:一个程序,程序的集合,比如一个音乐播发器,QQ程序等.一个进程往往包含 ...

  2. Java 并发编程学习笔记 理解CLH队列锁算法

    CLH算法实现 CLH队列中的结点QNode中含有一个locked字段,该字段若为true表示该线程需要获取锁,且不释放锁,为false表示线程释放了锁.结点之间是通过隐形的链表相连,之所以叫隐形的链 ...

  3. 并发编程学习笔记(13)----ConcurrentLinkedQueue(非阻塞队列)和BlockingQueue(阻塞队列)原理

    · 在并发编程中,我们有时候会需要使用到线程安全的队列,而在Java中如果我们需要实现队列可以有两种方式,一种是阻塞式队列.另一种是非阻塞式的队列,阻塞式队列采用锁来实现,而非阻塞式队列则是采用cas ...

  4. 并发编程学习笔记(14)----ThreadPoolExecutor(线程池)的使用及原理

    1. 概述 1.1 什么是线程池 与jdbc连接池类似,在创建线程池或销毁线程时,会消耗大量的系统资源,因此在java中提出了线程池的概念,预先创建好固定数量的线程,当有任务需要线程去执行时,不用再去 ...

  5. 并发编程学习笔记(5)----AbstractQueuedSynchronizer(AQS)原理及使用

    (一)什么是AQS? 阅读java文档可以知道,AbstractQueuedSynchronizer是实现依赖于先进先出 (FIFO) 等待队列的阻塞锁和相关同步器(信号量.事件,等等)提供一个框架, ...

  6. Java并发编程学习笔记

    Java编程思想,并发编程学习笔记. 一.基本的线程机制 1.定义任务:Runnable接口 线程可以驱动任务,因此需要一种描述任务的方式,这可以由Runnable接口来提供.要想定义任务,只需实现R ...

  7. 并发编程学习笔记(15)----Executor框架的使用

    Executor执行已提交的 Runnable 任务的对象.此接口提供一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节.调度等)分离开来的方法.通常使用 Executor 而不是显式地创建 ...

  8. 并发编程学习笔记(11)----FutureTask的使用及实现

    1. Future的使用 Future模式解决的问题是.在实际的运用场景中,可能某一个任务执行起来非常耗时,如果我们线程一直等着该任务执行完成再去执行其他的代码,就会损耗很大的性能,而Future接口 ...

  9. 并发编程学习笔记(12)----Fork/Join框架

    1. Fork/Join 的概念 Fork指的是将系统进程分成多个执行分支(线程),Join即是等待,当fork()方法创建了多个线程之后,需要等待这些分支执行完毕之后,才能得到最终的结果,因此joi ...

  10. 并发编程学习笔记(10)----并发工具类CyclicBarrier、Semaphore和Exchanger类的使用和原理

    在jdk中,为并发编程提供了CyclicBarrier(栅栏),CountDownLatch(闭锁),Semaphore(信号量),Exchanger(数据交换)等工具类,我们在前面的学习中已经学习并 ...

随机推荐

  1. 达梦数据库: SQL查询报错《不是 GROUP BY 表达式解决方法》

    报错信息: ****: 第4 行附近出现错误: 不是 GROUP BY 表达式 修改办法: 达梦可以配置兼容参数,COMPATIBLE_MODE=4,静态参数,需要重启数据库后生效! sp_set_p ...

  2. java反射newInstance()带删除线的问题

    从java9开始,newInstance()方法不建议使用导致idea自动画了条删除横线 解决方法: //改用getDeclaredConstructor().newInstance() Object ...

  3. RobotFrameWork环境搭建及使用

    RF环境搭建 首先安装python并且配置python环境变量 pip install robotframework pip install robotframework-ride 生产桌面快捷方式 ...

  4. Xshell使用技巧及常用配置

    Xshell使用 1.调整 Xshell 的终端显示和回滚缓冲区大小 磨刀不误砍柴工,为了更方便地学习 Linux,首先得对终端进行一些调整,步骤如下: 首先通过 xshell 顶部菜单中的文件--& ...

  5. 熟悉又陌生的package.json

    前言 随着前端的不断发展,package.json可谓是在前端项目中无处不在,它不仅在项目根目录会有,而且在 node_modules 中也存在.那么这个文件到底是干嘛的,又有什么作用?很多人对它的认 ...

  6. Baby_python 反编译

    ok,直接pyc直接反编译 逻辑清楚 拿到flag直接搞 结果提交给错了我把前缀改成flag{}这种格式也给错真是摸不着头脑 难道是base64解密错误?? 找了另外一个网站 ???这个是啥?? 与之 ...

  7. Feign的超时时间如何设置,我研究了4种情况

    大家好,我是三友~~ 今天来聊一聊前段时间看到的一个面试题,也是在实际项目中需要考虑的一个问题,Feign的超时时间如何设置? Feign的超时时间设置方式并不固定,它取决于Feign在项目中是如何使 ...

  8. Callback Function Essence

    Include Example Input: I am a. route execute finish. I am b. route execute finish. What is Callback ...

  9. Linux 内核音频子系统调试

    debugfs 文件系统 debugfs 可以为 Linux 内核各个模块的分析调试,提供许多信息,如音频子系统的 ASoC,以及 tracing 等.debugfs 文件系统可以通过命令行工具挂载, ...

  10. 这才叫 API 接口设计!

    API 接口设计 Token 设计 Token 是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个 Token 便将此 Token 返回给客户端,以后客户端只需带上 ...