ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue、ConcurrentLinkedQueue 和 DelayQueue 是 Java 中 java.util.concurrent 包提供的几种队列实现。它们都支持多线程环境下的安全操作,但在实现方式和特性上有所不同。
java.util.Queue 接口,并提供了类似的队列操作方法,如 offer(), poll(), peek() 等。Delayed 接口。有界与无界:
ArrayBlockingQueue 是有界的,必须指定容量。LinkedBlockingQueue 可有界也可无界。PriorityBlockingQueue、ConcurrentLinkedQueue 和 DelayQueue 是无界的。阻塞与非阻塞:
ArrayBlockingQueue、LinkedBlockingQueue 和 PriorityBlockingQueue 是阻塞队列,支持阻塞的操作。ConcurrentLinkedQueue 是非阻塞队列,使用 CAS 实现线程安全,不会阻塞线程。DelayQueue 是阻塞队列,但只有当元素的延迟到期时才能获取元素。使用场景:
ArrayBlockingQueue 适用于有容量限制的场景。LinkedBlockingQueue 适用于容量可能会变化或者不需要限制的场景。PriorityBlockingQueue 适用于需要按优先级处理元素的场景。ConcurrentLinkedQueue 适用于高并发、无界的场景。DelayQueue 适用于需要延迟执行或定时调度任务的场景。这些队列在不同的应用场景中提供了灵活性和并发性能,选择哪种队列取决于具体需求,如是否需要有界、是否需要阻塞操作、是否需要按优先级排序等。
下面分别列出 ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue、ConcurrentLinkedQueue 和 DelayQueue 的常用操作方法。所有这些队列都实现了 java.util.Queue 接口,因此一些通用的方法在这些类中都有定义。
添加和移除元素:
boolean add(E e):在队列尾部插入指定元素,如果成功返回 true,如果队列已满则抛出 IllegalStateException。boolean offer(E e):在队列尾部插入指定元素,如果成功返回 true,否则返回 false。E remove():移除并返回队列头部的元素,如果队列为空则抛出 NoSuchElementException。E poll():移除并返回队列头部的元素,如果队列为空则返回 null。E take():移除并返回队列头部的元素,若队列为空则等待直到有元素可用。boolean remove(Object o):从队列中移除指定元素(与 Queue 接口中定义的一致)。查看元素:
E element():返回队列头部的元素,但不移除。如果队列为空则抛出 NoSuchElementException。E peek():返回队列头部的元素,但不移除。如果队列为空则返回 null。其他方法:
int size():返回队列中的元素数量。int remainingCapacity():返回队列剩余的容量。boolean contains(Object o):检查队列中是否包含指定的元素。void clear():移除队列中的所有元素。添加和移除元素:
boolean add(E e):在队列尾部插入指定元素,如果队列已满则抛出 IllegalStateException。boolean offer(E e):在队列尾部插入指定元素,如果成功返回 true,否则返回 false。E remove():移除并返回队列头部的元素,如果队列为空则抛出 NoSuchElementException。E poll():移除并返回队列头部的元素,如果队列为空则返回 null。E take():移除并返回队列头部的元素,若队列为空则等待直到有元素可用。void put(E e):在队列尾部插入指定元素,如果队列满则等待。查看元素:
E element():返回队列头部的元素,但不移除。如果队列为空则抛出 NoSuchElementException。E peek():返回队列头部的元素,但不移除。如果队列为空则返回 null。其他方法:
int size():返回队列中的元素数量。int remainingCapacity():返回队列的剩余容量。boolean contains(Object o):检查队列中是否包含指定的元素。void clear():移除队列中的所有元素。添加和移除元素:
boolean add(E e):在队列中插入指定元素,队列根据元素的优先级进行排序。boolean offer(E e):在队列中插入指定元素,队列根据元素的优先级进行排序。E remove():移除并返回队列中具有最高优先级的元素,如果队列为空则抛出 NoSuchElementException。E poll():移除并返回队列中具有最高优先级的元素,如果队列为空则返回 null。E take():移除并返回队列中具有最高优先级的元素,如果队列为空则等待直到有元素可用。查看元素:
E element():返回队列中具有最高优先级的元素,但不移除。如果队列为空则抛出 NoSuchElementException。E peek():返回队列中具有最高优先级的元素,但不移除。如果队列为空则返回 null。其他方法:
int size():返回队列中的元素数量。boolean contains(Object o):检查队列中是否包含指定的元素。void clear():移除队列中的所有元素。添加和移除元素:
boolean add(E e):在队列尾部插入指定元素,如果成功返回 true。boolean offer(E e):在队列尾部插入指定元素,如果成功返回 true。E remove():移除并返回队列头部的元素,如果队列为空则抛出 NoSuchElementException。E poll():移除并返回队列头部的元素,如果队列为空则返回 null。查看元素:
E element():返回队列头部的元素,但不移除。如果队列为空则抛出 NoSuchElementException。E peek():返回队列头部的元素,但不移除。如果队列为空则返回 null。其他方法:
int size():返回队列中的元素数量。boolean contains(Object o):检查队列中是否包含指定的元素。void clear():移除队列中的所有元素。添加和移除元素:
boolean add(E e):在队列中插入指定元素,如果元素没有延迟则抛出 IllegalArgumentException。boolean offer(E e):在队列中插入指定元素,如果元素没有延迟则抛出 IllegalArgumentException。void put(E e):在队列中插入指定元素,如果元素没有延迟则抛出 IllegalArgumentException。E remove():移除并返回队列头部的元素,如果队列为空则抛出 NoSuchElementException。E poll():移除并返回队列头部的元素,如果没有元素到期则返回 null。E take():移除并返回队列头部的元素,如果没有元素到期则等待。查看元素:
E peek():返回队列头部的元素,但不移除。如果没有元素到期则返回 null。其他方法:
int size():返回队列中的元素数量。boolean contains(Object o):检查队列中是否包含指定的元素。void clear():移除队列中的所有元素。每个队列的具体方法可能略有不同,尤其是在处理阻塞、非阻塞、优先级和延迟方面时。选择哪种队列取决于应用程序的具体需求,如是否需要有序处理、是否需要延迟处理等。
下面列出 ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue、ConcurrentLinkedQueue 和 DelayQueue 的关键成员变量。这些成员变量定义了队列的内部状态和行为。
ArrayBlockingQueue 是一个基于数组的有界阻塞队列,以下是其主要成员变量:
items
Object[]ArrayBlockingQueue 是基于数组的实现。count
inttakeIndex
intputIndex
intlock
ReentrantLocknotEmpty
ConditionnotFull
Conditionfair
booleanLinkedBlockingQueue 是一个基于链表的阻塞队列,可以有界也可以无界,以下是其主要成员变量:
head
Nodelast
Nodecount
AtomicIntegercapacity
intInteger.MAX_VALUE。takeLock
ReentrantLockputLock
ReentrantLocknotEmpty
ConditionnotFull
ConditionPriorityBlockingQueue 是一个基于堆的无界优先级队列,以下是其主要成员变量:
queue
Object[]size
intcomparator
Comparator super E>lock
ReentrantLocknotEmpty
ConditionConcurrentLinkedQueue 是一个基于链表的无界非阻塞队列,以下是其主要成员变量:
head
AtomicReference> Node 是链表的节点类。tail
AtomicReference> DelayQueue 是一个基于堆的无界阻塞队列,专门处理带有延迟时间的元素,以下是其主要成员变量:
queue
PriorityQueueleader
Threadlock
ReentrantLockavailable
Condition这些成员变量是每个队列的核心组成部分,决定了它们的内部数据结构、并发控制机制和操作行为。了解这些成员变量及其作用有助于深入理解这些队列的实现原理和使用场景。
在介绍的几种 Java 并发队列中,有些队列有其独特的特性或使用场景。以下是对一些关键特性和场景的特殊解释:
ArrayBlockingQueue 是一个有界的阻塞队列,这意味着它有一个固定的容量。当队列满时,尝试向队列添加新元素的操作将被阻塞,直到有空间可用。类似地,当队列为空时,尝试从队列获取元素的操作也会被阻塞,直到有新元素可用。LinkedBlockingQueue 基于链表实现,可以是有界也可以是无界的。即使在容量设置上,它也有可能在实际使用中表现为无界(例如容量非常大时)。PriorityBlockingQueue 是一个无界队列,它的特殊之处在于内部维护了元素的优先级顺序。元素按优先级顺序进行排列,优先级最高的元素会先被处理。它使用自然顺序或自定义的比较器来确定优先级。ConcurrentLinkedQueue 是无阻塞的,这意味着它不使用传统的锁机制,而是利用 CAS(Compare-And-Swap)操作来实现线程安全。这个特性使得它在高并发情况下性能非常好,因为线程不会因为锁竞争而阻塞。DelayQueue 是一个无界的优先级队列,但其特殊之处在于元素必须实现 Delayed 接口。每个元素都有一个到期时间,只有到期的元素才能被从队列中取出。在某些情况下,元素可能永远不会到期,因此需要仔细管理元素的生命周期。ArrayBlockingQueue 和 LinkedBlockingQueue:适用于生产者-消费者模式,特别是在需要有界控制(如限制资源使用)的情况下。PriorityBlockingQueue:适用于需要根据优先级处理任务的场景,如任务调度系统。ConcurrentLinkedQueue:适合在需要快速无锁操作的高并发场景,如日志记录系统、事件处理系统等。DelayQueue:用于需要延迟执行的场景,如定时任务、限时缓存等。每种队列都有其独特的设计和用途,理解其特性有助于在合适的场景中选择合适的队列,以实现最佳的性能和正确性。