9. 阻塞队列

news/2024/5/20 7:18:59 标签: java, 线程, 多线程, juc, 并发

阻塞队列是共享队列(多线程操作),一端输入,一端输出
不能无限放队列,满了之后就会进入阻塞,取出也同理

    当队列是空的,从队列中获取元素的操作将会被阻塞
    当队列是满的,从队列中添加元素的操作将会被阻塞
    试图从空的队列中获取元素的线程将会被阻塞,直到其他线程往空的队列插入新的元素
    试图向已满的队列中添加新元素的线程将会被阻塞,直到其他线程从队列中移除一个或多个元素或者完全清空,使队列变得空闲起来并后续新增

9.1 种类

1.ArrayBlockingQueue
基于数组的阻塞队列
由数组结构组成的有界阻塞队列
-ArrayBlockingQueue 在生产者放入数据和消费者获取数据,都是共用同一个锁对象,无法并行

2. LinkedBlockingQueue
基于链表的阻塞队列
由链表结构组成的有界(但大小默认值为integer.MAX_VALUE)阻塞队列

    之所以能够高效的处理并发数据,还因为其对于生产者端和消费者端分别采用了独立的锁来控制数据同步,这也意味着在高并发的情况下生产者和消费者可以并行地操作队列中的数据,以此来提高整个队列的并发性能

3.DelayQueue
使用优先级队列实现的延迟无界阻塞队列

    DelayQueue 中的元素只有当其指定的延迟时间到了,才能够从队列中获取到该元素。DelayQueue 是一个没有大小限制的队列,因此往队列中插入数据的操作(生产者)永远不会被阻塞,而只有获取数据的操作(消费者)才会被阻塞

4.PriorityBlockingQueue
基于优先级的阻塞队列
支持优先级排序的无界阻塞队列
不会阻塞数据生产者,而只会在没有可消费的数据时,阻塞数据的消费者

5.SynchronousQueue
一种无缓冲的等待队列
相对于有缓冲的 BlockingQueue 来说,少了一个中间经销商的环节(缓冲区)
不存储元素的阻塞队列,也即单个元素的队列

声明一个 SynchronousQueue 有两种不同的方式,它们之间有着不太一样的行为。
公平模式和非公平模式的区别:
• 公平模式:SynchronousQueue 会采用公平锁,并配合一个 FIFO 队列来阻塞
多余的生产者和消费者,从而体系整体的公平策略;
• 非公平模式(SynchronousQueue 默认):SynchronousQueue 采用非公平锁,同时配合一个 LIFO 队列来管理多余的生产者和消费者

而后一种模式,如果生产者和消费者的处理速度有差距,则很容易出现饥渴的情况,即可能有某些生产者或者是消费者的数据永远都得不到处理

6.LinkedTransferQueue
由链表结构组成的无界阻塞 TransferQueue 队列
由链表组成的无界阻塞队列

    预占模式。意思就是消费者线程取元素时,如果队列不为空,则直接取走数据,若队列为空,生成一个节点(节点元素为 null)入队,消费者线程被等待在这个节点上,生产者线程入队时发现有一个元素为 null 的节点,生产者线程就不入队了,直接就将元素填充到该节点,并唤醒该节点等待的线程,被唤醒的消费者线程取走元素,从调用的方法返回

7.LinkedBlockingDeque
由链表结构组成的双向阻塞队列
阻塞有两种情况

    插入元素时: 如果当前队列已满将会进入阻塞状态,一直等到队列有空的位置时再该元素插入,该操作可以通过设置超时参数,超时后返回 false 表示操作失败,也可以不设置超时参数一直阻塞,中断后抛出 InterruptedException异常
    读取元素时: 如果当前队列为空会阻塞住直到队列不为空然后返回元素,同样可以通过设置超时参数

9.2 方法

第一种方法:

创建阻塞队列 BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);

    加入元素System.out.println(blockingQueue.add("a"));,成功为true,失败为false
    检查元素System.out.println(blockingQueue.element());
    取出元素System.out.println(blockingQueue.remove());,先进先出

第二种方法:
加入元素System.out.println(blockingQueue.offer("a"));
取出元素System.out.println(blockingQueue.poll());

第三种方法:
加入元素blockingQueue.put("a");
取出元素System.out.println(blockingQueue.take());

该方法加入元素或者取出元素,如果满了或者空了,还进行下一步加入或者取出操作,会出现阻塞的状态,而第一二种方法是直接抛出异常

第四种方法:
加入元素System.out.println(blockingQueue.offer("a"));
该方法满了或者空了在进行会有阻塞,但可以加入参数,超时退出System.out.println(blockingQueue.offer("w",3L, TimeUnit.SECONDS));
 


http://www.niftyadmin.cn/n/1712918.html

相关文章

数据结构————线性表的实现 合并

1、表的实现 1.1表的数组表示 线性表的定义&#xff1a;线性表是n个元素的有限序列&#xff0c;表中各个数据元素具有相同特性&#xff0c;属于同一数据对象。 #include <stdio.h> #include <stdlib.h>#define TRUE 1 #define FALSE 0 #define OK 1 #define ERR…

10. 线程池

连接池是创建和管理一个连接的缓冲池的技术&#xff0c;这些连接准备好被任何需要它们的线程使用 线程池&#xff08;英语&#xff1a;thread pool&#xff09;一种线程使用模式。线程过多会带来调度开销&#xff0c;进而影响缓存局部性和整体性能。而线程池维护着多个线程&am…

数据结构———插入排序(希尔排序,折半插入,直接插入)

排序 直接插入排序 直接插入排序。对于少量元素的排序&#xff0c;它是一个有效的算法 。插入排序是一种最简单的排序方法&#xff0c;它的基本思想是将一个记录插入到已经排好序的有序表中&#xff0c;从而一个新的、记录数增1的有序表。在其实现过程使用双层循环&#xff0…

11. Fork与Join分支

将一个大的任务拆分成多个子任务进行并行处理&#xff0c;最后将子任务结果合并成最后的计算结果 该算法相当于递归&#xff0c;且是二分查找思路 八种基本排序问题 &#xff08;第六篇 归并排序&#xff09;图文详解_想成为大神说32的博客-CSDN博客 class Fibonacci extends…

数据结构——交换排序(冒泡排序和快速排序。)

交换排序 所谓交换&#xff0c;就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置&#xff0c;交换排序的特点是&#xff1a;将键值较大的记录向序列的尾部移动&#xff0c;键值较小的记录向序列的前部移动。 冒泡排序 1、比较相邻的元素。如果第一个比第…

12. 异步回调

CompletableFuture 在 Java 里面被用于异步编程&#xff0c;异步通常意味着非阻塞&#xff0c;可以使得我们的任务单独运行在与主线程分离的其他线程中&#xff0c;并且通过回调可以在主线程中得到异步任务的执行状态&#xff0c;是否完成&#xff0c;和是否异常等信息 类中的…

数据结构————哈希表的实现(语言)

哈希表 散列表&#xff08;Hash table&#xff0c;也叫哈希表&#xff09;&#xff0c;是根据关键码值(Key value)而直接进行访问的数据结构。也就是说&#xff0c;它通过把关键码值映射到表中一个位置来访问记录&#xff0c;以加快查找的速度。这个映射函数叫做散列函数&…

排序算法(对三个数进行排序三指针)

思路 采用三个指针 1&#xff09;头指针之前都是第一个数 2&#xff09;尾指针之后都是地三个数 3&#xff09;两个指针之间是第二个数 看一下例子&#xff1a; 例如对{1&#xff0c;0&#xff0c;0&#xff0c;2&#xff0c;2&#xff0c;1&#xff0c;0&#xff0c;2}进行排…