你使用过 Java 中的哪些阻塞队列?

Sherwin.Wei Lv7

你使用过 Java 中的哪些阻塞队列?

回答重点

阻塞队列主要用来阻塞队列的插入和获取操作,当队列满了的时候插入操作会被阻塞,直到队列有空位。当队列为空的时候获取操作会被阻塞,直到队列有值。

常用在实现生产者和消费者场景,在笔试题中比较常见。

常见的阻塞队列包括:

  • ArrayBlockingQueue:一个有界队列,底层基于数组实现。需要在初始化时指定队列的大小,队列满时,生产者会被阻塞,队列空时,消费者会被阻塞。
  • LinkedBlockingQueue:基于链表的阻塞队列,允许可选的界限(有界或无界)。无界模式下可以不断添加元素,直到耗尽系统资源。有界模式则类似于 ArrayBlockingQueue,但吞吐量通常较高。
  • PriorityBlockingQueue:一个无界的优先级队列,元素按照自然顺序或者指定的比较器顺序进行排序。与其他阻塞队列不同的是,PriorityBlockingQueue 不保证元素的 FIFO 顺序。
  • DelayQueue:一个无界队列,队列中的元素必须实现 Delayed 接口,只有当元素的延迟时间到期时,才能被取出。常用于延迟任务调度。
  • SynchronousQueue:一个没有内部容量的队列,每个插入操作必须等待对应的移除操作,反之亦然。常用于在线程之间的直接传递任务,而不是存储任务。

扩展知识

使用场景

  • ArrayBlockingQueueLinkedBlockingQueue 常用于典型的生产者-消费者场景。例如:任务处理系统中,生产者生成任务,消费者从队列中取出任务并执行。
  • PriorityBlockingQueue 更适合处理带有优先级的任务场景,如任务调度系统。
  • DelayQueue 适用于需要延迟处理的任务,例如:缓存失效策略、定时任务调度等。
  • SynchronousQueue 适合在线程间直接传递数据,而不希望数据被存储在队列中。例如:ThreadPoolExecutor 的直接交接模式中使用 SynchronousQueue 来传递任务。

ArrayBlockingQueue 和 LinkedBlockingQueue 区别

常见的有 ArrayBlockingQueue 和 LinkedBlockingQueue,分别是基于数组和链表的有界阻塞队列。

两者原理都是基于 ReentrantLock 和 Condition 。

ArrayBlockingQueue 基于数组,内部实现只用了一把锁,可以指定公平或者非公平锁。

LinkedBlockingQueue 基于链表,内部实现用了两把锁,take 一把、put 一把,所以入队和出队这两个操作是可以并行的,从这里看并发度应该比 ArrayBlockingQueue 高。

LinkedTransferQueue

LinkedTransferQueue,相对于其他阻塞队列从名字来看它有 Transfer 功能,其实也不是什么神奇功能,一般阻塞队列都是将元素入队,然后消费者从队列中获取元素。

而 LinkedTransferQueue 的 transfer 是元素入队的时候看看是否已经有消费者在等了,如果有在等了直接给消费者即可,所以就是这里少了一层,没有锁操作。

Comments