• 多线程案例(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. }
  • 相关阅读:
    【Linux从0-1 】之 - 什么是Linux?Linux与Unix有什么区别?Linux的几个主流发行版本
    人工智能轨道交通行业周刊-第60期(2023.9.11-9.17)
    工厂模式代码实例详解
    开源系统的组成组件(邮件,在线交流,版本控制)
    如何制定LinkedIn商进行品牌推广?
    查询截取分析_慢查询日志
    EasyExcel使用方式(包含导出图片)
    开发者新手指南:一文汇总 Web3 开发工具
    Python os模块
    Python-井字棋
  • 原文地址:https://blog.csdn.net/m0_74859835/article/details/132866456