• 多线程案例(2) - 阻塞队列


    目录

    一,阻塞队列

    1.1 什么是阻塞队列

    1.2 生产者消费者模型

    1.3 标准库中的阻塞队列

    1.4 阻塞队列的实现


    一,阻塞队列

    1.1 什么是阻塞队列

    阻塞队列(BlockingQueue)是一种特殊的队列,遵循 "先进先出" 的原则,它有两个特点:1. 队列为空时等待获取元素。2. 队列已满时等待插入元素的操作。具体来说,当一个线程试图从空的阻塞队列中获取元素时,该线程将被阻塞,直到队列中有可用元素为止。同样地,当一个线程试图向已满的阻塞队列中插入元素时,该线程将被阻塞,直到队列中有空闲位置为止。

    1.2 生产者消费者模型

    阻塞队列通常用于实现生产者-消费者模式,其中生产者线程将数据放入队列,而消费者线程从队列中取出数据进行处理。那么这么做有什么好处呢?

    1.  阻塞队列类似于一个缓冲区,可以平衡生产者和消费者的处理能力,比如:在318,双11这些日子的时候,服务器会在同一时刻收到大量的购物订单,如果一股脑的交给一个服务器可能扛不住,这个时候就可以把这些订单放入到阻塞队列中,然后再由服务器慢慢处理每个订单,再举一个生活中的例子,三峡大坝(阻塞队列),当汛期到来时,三峡大坝会将多余的水储存住,防止下游出现洪涝灾害,等到枯水期的时候,再将储存的水排到下游,起到了 "削峰填谷" 的作用。
    2. 能够使代码解耦合,简单来说,就是降低代码之间的联系,这样就不会出现 "牵一发而动全身" 的现象。

    1.3 标准库中的阻塞队列

    标准库中提供了一个BlockingQueue的接口,它继承了Queue类,所以它包含Queue的所有方法,常见的阻塞队列实现包括ArrayBlockingQueue、LinkedBlockingQueue等。我们通常使用这些类中的 put() 和 take() 方法,因为其他的方法不具备 "阻塞" 特性。

    1. import java.util.concurrent.*;
    2. public class Demo {
    3. public static void main(String[] args) throws InterruptedException {
    4. BlockingQueue blockingQueue = new LinkedBlockingQueue<>();
    5. blockingQueue.put("111");
    6. String t = blockingQueue.take();
    7. }
    8. }

    1.4 阻塞队列的实现

    这里我们使用循环数组的方式来实现阻塞队列。

    1. public class MyBlockingQueue {
    2. private int[] arr = new int[10];//队列
    3. //防止出现内存可见性的问题
    4. private volatile int head;//
    5. private volatile int tail;//
    6. private volatile int size;//已经存了几个元素
    7. public MyBlockingQueue(){
    8. head = 0;
    9. tail = 0;
    10. size = 0;
    11. }
    12. public void put(int val) throws InterruptedException {
    13. synchronized (this){
    14. if(size == arr.length){
    15. this.wait();//队列满了,阻塞
    16. }
    17. arr[tail] = val;
    18. tail = (tail+1)%arr.length;
    19. size++;
    20. this.notify();//唤醒take()中的wait()
    21. }
    22. }
    23. public int take() throws InterruptedException {
    24. synchronized (this) {
    25. if(size == 0){
    26. this.wait();//队列为空,阻塞
    27. }
    28. int tmp = arr[head];
    29. head = (head+1)%arr.length;
    30. size--;
    31. this.notify();//唤醒put()中的wait()
    32. return tmp;
    33. }
    34. }
    35. }
  • 相关阅读:
    【strcat函数和strncat函数的对比与模拟实现】
    股票数据分析应用之可视化图表组件
    2024.2.25 模拟实现 RabbitMQ —— 网络通信设计(服务器)
    (数据科学学习手札135)tenacity:Python中最强大的错误重试库
    目录的权限
    RabbitMQ: 死信队列
    2022中国DevOps社区峰会 走进国产数据库的技术创新实践
    2023下半年软考各地区准考证打印时间汇总
    Debezium日常分享系列之:Debezium 2.3.0.Final发布
    RK3588 开发者选项中通过“USB DEBUG“按钮实现otg模式切换(二)
  • 原文地址:https://blog.csdn.net/m0_74859835/article/details/132866456