阻塞队列

阻塞

队列

队列的特性: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. sshpass快速登录远程主机:s2

    #!/bin/bash passwd= if [ $# -ne 1 ] then echo "$0 [31|37|61]" fi if command -v sshpass the ...

  2. 2021-7-6 new tcpip

    using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Ne ...

  3. Pytorch 最全入门介绍,Pytorch入门看这一篇就够了

    本文通过详细且实践性的方式介绍了 PyTorch 的使用,包括环境安装.基础知识.张量操作.自动求导机制.神经网络创建.数据处理.模型训练.测试以及模型的保存和加载. 1. Pytorch简介 在这一 ...

  4. 2023-07-31:用r、e、d三种字符,拼出一个回文子串数量等于x的字符串。 1 <= x <= 10^5。 来自百度。

    2023-07-31:用r.e.d三种字符,拼出一个回文子串数量等于x的字符串. 1 <= x <= 10^5. 来自百度. 答案2023-07-31: 大体步骤如下: 1.初始化一个字符 ...

  5. JS优化技巧,解决冗余代码

    1. 使用箭头函数简化函数定义 // 传统函数定义 function add(a, b) { return a + b; } // 箭头函数简化 const add = (a, b) => a ...

  6. python中的注释noqa: F401

    在Python中,"noqa: F401" 是一个特殊的注释指示.它主要用于在静态代码检查工具(例如Flake8)运行时,告知工具忽略特定的 "F401" 错误 ...

  7. 【go笔记】TCP编程

    前言 TCP服务端的处理流程 监听端口 接收客户端请求建立连接 创建goroutine处理链接 示例代码:TCP服务端 package main import ( "net" &q ...

  8. python机器学习经典算法代码示例及思维导图(数学建模必备)

    最近几天学习了机器学习经典算法,通过此次学习入门了机器学习,并将经典算法的代码实现并记录下来,方便后续查找与使用. 这次记录主要分为两部分:第一部分是机器学习思维导图,以框架的形式描述机器学习开发流程 ...

  9. Vue3 中 keepAlive 如何搭配 VueRouter 来更自由的控制页面的状态缓存?

    在 vue 中,默认情况下,一个组件实例在被替换掉后会被销毁.这会导致它丢失其中所有已变化的状态--当这个组件再一次被显示时,会创建一个只带有初始状态的新实例.但是 vue 提供了 keep-aliv ...

  10. 图解Spark Graphx基于connectedComponents函数实现连通图底层原理

    原创/朱季谦 第一次写这么长的graphx源码解读,还是比较晦涩,有较多不足之处,争取改进. 一.连通图说明 连通图是指图中的任意两个顶点之间都存在路径相连而组成的一个子图. 用一个图来说明,例如,下 ...