阻塞队列

阻塞

队列

队列的特性: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. 巧用 nc 命令传输文件

    今天在业务上云的时候,遇到了些问题.最终发现问题的根源不好排查,于是-- 把生产环境的全量配置文件,还有日志全量打包下载到开发机器分析! 刚入职不是很久的整个运维团队,也不是很熟悉生产环境(有时候觉得 ...

  2. boinc使用笔记

    安装 yum install -y epel-release yum install -y boinc-client boinc-manager 启动 在图形界面开启终端 boinc boincmgr

  3. 基于 Spark 的物流企业数据仓库 的设计与实现

    1.设计和实现了一种基于 Spark 的分布式 ETL 系统,包括利用 Spark 抽取.转换清洗和加载数据的具体过程. 2.设计和实现了基于 Spark 的物流企业数据仓库,包括物流企业数据仓库的分 ...

  4. js 关于 replace 取值、替换第几个匹配项(两种方式:正则、普通字符串操作)

    〇.前言 在日常开发中,经常遇到针对字符串的替换.截取,知识点比较碎容易混淆,特此总结一下,仅供参考. 一.替换第一个匹配项 字符串替换 let strtest = "0123测试repla ...

  5. 【pandas小技巧】--反转行列顺序

    反转pandas DataFrame的行列顺序是一种非常实用的操作.在实际应用中,当我们需要对数据进行排列或者排序时,通常会使用到Pandas的行列反转功能.这个过程可以帮助我们更好地理解数据集,发现 ...

  6. Codeforces 1855B:Longest Divisors Interval 最长的连续约数区间

    1855B.Longest Divisors Interval Description: 对于一个整数 \(n\) \((1\leq n \leq 10^{18})\),找到一段最长的区间\([l,r ...

  7. [kafka]常见术语

    前言 kafka属于分布式的消息引擎系统,主要功能是提供一套完备的消息发布与订阅解决方案. 消息和批次 kafka 的数据单元被称为消息.消息由字节数组组成,对kafka来说,消息里的数据没有特殊的格 ...

  8. [ABC126E] 1 or 2

    2023-01-07 题目 题目传送门 翻译 翻译 难度&重要性(1~10):2 题目来源 AtCoder 题目算法 并查集 解题思路 因为每张卡片上的数字只能是 \(1\) 或者 \(2\) ...

  9. ELK环境部署-基础环境安装(一)

    ELK简介 ElasticSearch工作原理以及专用名词 ELK是Elasticsearch(ES) , Logstash, Kibana的结合,是一个开源日志收集软件. Elasticsearch ...

  10. SqlServer修改表字段类型

    if not exists (select 1 from syscolumns where name='字段名' and id=OBJECT_ID('表名') and 条件) begin alter ...