【JavaEE】多线程(5) -- 阻塞队列

目录

1.阻塞队列是什么?

2.生产者消费者模型

3.标准库中的阻塞队列

4.阻塞队列的实现


1.阻塞队列是什么?

阻塞队列是⼀种特殊的队列. 也遵守 "先进先出" 的原则

阻塞队列能是⼀种线程安全的数据结构, 并且具有以下特性:

当队列满的时候, 继续⼊队列就会阻塞, 直到有其他线程从队列中取⾛元素.

 当队列空的时候, 继续出队列也会阻塞, 直到有其他线程往队列中插⼊元素.

阻塞队列的⼀个典型应⽤场景就是 "⽣产者消费者模型". 这是⼀种⾮常典型的开发模型.

2.生产者消费者模型

⽣产者消费者模式就是通过⼀个容器来解决⽣产者和消费者的强耦合问题。 ⽣产者和消费者彼此之间不直接通讯,⽽通过阻塞队列来进⾏通讯,所以⽣产者⽣产完数据之后不⽤ 等待消费者处理,直接扔给阻塞队列,消费者不找⽣产者要数据,⽽是直接从阻塞队列⾥取.

实际开发中, 经常会涉及到 "分布式系统", 服务器整个功能不是由一个服务器全部完成的. 而是每个服务器负责一部分功能, 通过服务器之间的网络通信, 最终完成整个功能.

上述过程中, A 和 B , A 和 C 之间的耦合性是比较轻的, A中的代码需要设计到一些B相关的操作, B中的代码也涉及到和A相关的操作,   A 的代码中也需要涉及和 C 相关的操作, C 的代码也涉及和 A 相关的操作, 另外, 如果 B 或者 C 服务器出现故障, 对 A 的影响就很大.

引用生产者消费者模型, 就可以降低上述的耦合

这样 A B C 之间就不是直接交互了, 而是通过队列在中间经常传递.

3.标准库中的阻塞队列

使用实例:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ThreadDemo28 {
    public static void main(String[] args) throws InterruptedException {
        BlockingQueue<String> queue = new ArrayBlockingQueue<>(100);
        queue.put("hello");
        System.out.println(queue.take());
        System.out.println(queue.take());

    }
}

当队列中的元素为空时, 在执行 take() 方法, 进程就会进入阻塞状态:

此时进程并会不结束.

4.阻塞队列的实现

基于环形队列来简单实现阻塞队列:

import static java.lang.Thread.sleep;

class MyBlockingQueue {
    private String[] elems = null;
    private int head = 0;
    private int tail = 0;
    private int size = 0;
    Object locker = new Object();

    public MyBlockingQueue(int capacity) {
        elems = new String[capacity];
    }

    public void put(String elem) throws InterruptedException {
        synchronized (locker) {
            while(size >= elem.length()) {
                //队列满了就阻塞
                locker.wait();
            }

            elems[tail] = elem;
            tail++;
            if(tail >= elems.length) {
                tail = 0;
            }
            size++;

            // 入队列成功后唤醒
            locker.notify();
        }
    }

    public String take() throws InterruptedException {
        String elem = null;
        synchronized (locker) {
            while(size == 0) {
                // 队列空了
                // 也需要这个代码阻塞
                locker.wait();
            }

            elem = elems[head];
            head++;
            if(head >= elems.length) {
                head = 0;
            }
            size--;

            //元素出队列成功后, 唤醒
            locker.notify();
        }

        return elem;
    }
}

细节注意:

基于阻塞队列实现简单的生产者消费者模型:

public class ThreadDeom29 {
    public static void main(String[] args) {
        MyBlockingQueue queue = new MyBlockingQueue(1000);
        //生产者
        Thread t1 = new Thread(()->{
            int n = 1;
            while(true) {
                try {
                    queue.put(n + "");
                    System.out.println("生产元素 " + n);
                    sleep(1000);
                    n++;
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });

        //消费者
        Thread t2 = new Thread(()-> {
            while(true) {
                try {
                    String n = queue.take();
                    System.out.println("消费元素 " + n);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });

        t1.start();
        t2.start();
    }
}

t1线程每隔一秒钟存放一个元素到阻塞队列中, t2 线程则在队列中有元素时将元素取出, 队列没有元素就进入阻塞状态, 直到队列不再为空 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/254062.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

论文阅读二——基于全脸外观的凝视估计

论文阅读二——基于全脸外观的凝视估计 基础知识主要内容文章中需要学习的架构AlexNet 代码复现 该论文是2017年在CVPR中发表的一篇关于 “gaze estimation” 的文章&#xff0c;其论文地址与代码地址如下&#xff1a; 论文地址 代码地址 论文特点&#xff1a;文章提出了一种…

IT和业务部门都想要的数据摆渡产品是这样的!

企业只要进行了网络隔离&#xff0c;就必然会需要数据摆渡相关产品&#xff0c;不管是免费的也好&#xff0c;专业收费的也好&#xff0c;总之都是需要将数据流转起来进行使用。 传统的数据摆渡产品也不少&#xff0c;比如FTP&#xff0c;甚至是U盘拷贝&#xff0c;在功能上来说…

Java数组(2)

我是南城余&#xff01;阿里云开发者平台专家博士证书获得者&#xff01; 欢迎关注我的博客&#xff01;一同成长&#xff01; 一名从事运维开发的worker&#xff0c;记录分享学习。 专注于AI&#xff0c;运维开发&#xff0c;windows Linux 系统领域的分享&#xff01; 本…

Docker容器如何优雅地访问宿主机网络

# 前言 某些时候&#xff0c;我们会有在容器内容访问宿主机某个服务的需求&#xff0c;比如现在 openai 无法直接访问&#xff0c;需要给项目添加代理&#xff0c;我的 chatgpt-dingtalk (opens new window) 项目支持了通过环境变量指定代理地址。 添加方式如下&#xff1a; …

微信小程序(五)地图

一、引言 作者开发《目的地到了》需要满足用户选取地址作为目的地的需求&#xff0c;所以需要使用到地图。作者用的是腾讯地图&#xff0c;这里介绍下技术实现。 二、引包 引入腾讯地图的组件包微信小程序JavaScript SDK | 腾讯位置服务&#xff0c;根据经纬度调用里面的api才…

5款不可或缺的办公软件,好用且使用频率超高,几乎每个人都需要

在当今数字化时代&#xff0c;办公软件成为了现代职场必备的工具。这些软件可以大大提高我们的办公效率&#xff0c;简化工作流程&#xff0c;使我们更加高效地完成任务。今天给大家分享5款不可或缺的办公软件&#xff0c;它们不仅好用&#xff0c;而且使用频率极高&#xff0c…

【PWN】学习笔记(三)【返回导向编程】(中)

目录 课程回顾动态链接过程 课程 课程链接&#xff1a;https://www.bilibili.com/video/BV1854y1y7Ro/?vd_source7b06bd7a9dd90c45c5c9c44d12e7b4e6 课程附件&#xff1a; https://pan.baidu.com/s/1vRCd4bMkqnqqY1nT2uhSYw 提取码: 5rx6 回顾 管道符 | 把前一个指令的输出作…

【C++高阶(七)】C++异常处理的方式

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:C从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习C   &#x1f51d;&#x1f51d; 异常处理的方式 1. 前言2. C语言处理异常的方式…

JVM-1-运行时数据区

程序计数器&#xff08;Program Counter Register&#xff09; 是一块较小的内存空间&#xff0c;它可以看作是当前线程所执行的字节码的行号指示器。在Java虚拟机的概念模型里[1]&#xff0c;字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令&…

centos安装了curl却报 -bash: curl: command not found

前因 我服务器上想用curl下载docker-compress&#xff0c;发现没有curl命令&#xff0c;就去下载安装&#xff0c;安装完成之后&#xff0c;报-bash: curl: command not found 解决方法 [rootcentos ~]# rpm -e --nodeps curl warning: file /usr/bin/curl: remove failed: …

AIGC实战——条件生成对抗网络(Conditional Generative Adversarial Net, CGAN)

AIGC实战——条件生成对抗网络 0. 前言1. CGAN架构2. 模型训练3. CGAN 分析小结系列链接 0. 前言 我们已经学习了如何构建生成对抗网络 (Generative Adversarial Net, GAN) 以从给定的训练集中生成逼真图像。但是&#xff0c;我们无法控制想要生成的图像类型&#xff0c;例如控…

Nat Med | Tau靶向反义寡核苷酸

今天给同学们分享一篇实验文章“Tau-targeting antisense oligonucleotide MAPTRx in mild Alzheimers disease: a phase 1b, randomized, placebo-controlled trial”&#xff0c;这篇文章发表在Nat Med期刊上&#xff0c;影响因子为82.9。 结果解读&#xff1a; 患者 从201…

防止反编译,保护你的SpringBoot项目

ClassFinal-maven-plugin插件是一个用于加密Java字节码的工具&#xff0c;它能够保护你的Spring Boot项目中的源代码和配置文件不被非法获取或篡改。下面是如何使用这个插件来加密test.jar包的详细步骤&#xff1a; 安装并设置Maven&#xff1a; 首先确保你已经在你的开发环境中…

关于#c语言#的问题:分析递归调用的过程◇画出调用过程各语句执行过程

关于#c语言#的问题&#xff1a;分析递归调用的过程◇画出调用过程各语句执行过程 当涉及到递归调用的过程时&#xff0c;可以通过绘制函数调用栈来分析和理解递归的执行过程。下面是一个示例的C语言递归函数和相应的调用过程&#xff1a; #include <stdio.h>void recurs…

数据结构 AVL树概念以及实现插入的功能(含Java代码实现)

为啥要有avl树 avl树是在二叉搜索树下的一种进阶形式,是为了防止二叉搜索树在极端情况下产生的链表化的场景,从而在二叉搜索树的基础上,加上了某些条件来阻止这种极端情况的产生,但不是保证完全平衡,而是放开了一定的条件,使得这种情况不那么难以满足.(条件:左右子树的高度差的…

【【UART 传输数据实验】】

UART 传输数据实验 通信方式在日常的应用中一般分为串行通信&#xff08;serial communication&#xff09;和并行通信&#xff08;parallel communication&#xff09;。 我们再来了解下串行通信的特点。串行通信是指数据在一条数据线上&#xff0c;一比特接一比特地按顺序传…

Python 爬虫开发完整环境部署,爬虫核心框架安装

Python 爬虫开发完整环境部署 前言&#xff1a; ​ 关于本篇笔记&#xff0c;参考书籍为 《Python 爬虫开发实战3 》 笔记做出来的一方原因是为了自己对 Python 爬虫加深认知&#xff0c;一方面也想为大家解决在爬虫技术区的一些问题&#xff0c;本篇文章所使用的环境为&#x…

Esxi中的AlmaLinux硬盘扩容

Esxi中的AlmaLinux硬盘扩容 通过本文能学习到 虚拟机中的AlmaLinux硬盘扩容 本文主要包括3部分内容&#xff1a; 1. 需要进行扩容的原因 2. 写这篇文章的目的 3. 扩容实操需要进行扩容的原因 近日&#xff0c;使用Jenkins部署时&#xff0c;出现镜像向Nexus私服推送镜像时…

展示一段比较简单的人工智能自动做模型的程序

人工智能是一种模拟或模仿人类智能的技术。它通过使计算机系统具有一定的认知能力和学习能力&#xff0c;使其能够自动完成一系列复杂的任务。人工智能可以在各个领域应用&#xff0c;包括图像识别、语音识别、自然语言处理、机器学习等。人工智能还可以用于解决各种问题&#…

互联网加竞赛 python 机器视觉 车牌识别 - opencv 深度学习 机器学习

1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于python 机器视觉 的车牌识别系统 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;3分创新点&#xff1a;3分 &#x1f9ff; 更多资…