java.util.concurrent.BlockingQueue
是一个接口,它通常实现的是先进先出(FIFO)的队列。默认情况下,BlockingQueue
的实现类(如 LinkedBlockingQueue
)不支持将消息插入到队列的头部。但是,可以通过以下方法实现将消息插入到队列的头部:
方法 1:使用 Deque
实现的双端队列
Deque
(双端队列)支持在队列的头部和尾部插入元素。LinkedBlockingDeque
是 BlockingQueue
的一个实现类,同时实现了 Deque
接口,因此可以在队列的头部插入元素。
示例代码
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.BlockingQueue;
public class InsertToHeadExample {
public static void main(String[] args) throws InterruptedException {
// 使用 LinkedBlockingDeque 实现 BlockingQueue
BlockingQueue<String> queue = new LinkedBlockingDeque<>();
// 向队列尾部插入元素
queue.offer("Tail1");
queue.offer("Tail2");
// 向队列头部插入元素
((LinkedBlockingDeque<String>) queue).offerFirst("Head1");
((LinkedBlockingDeque<String>) queue).offerFirst("Head2");
// 打印队列内容
while (!queue.isEmpty()) {
System.out.println(queue.poll());
}
}
}
输出
Head2
Head1
Tail1
Tail2
说明
LinkedBlockingDeque
是BlockingQueue
的实现类,同时支持在队列头部和尾部插入元素。- 使用
offerFirst()
方法可以将元素插入到队列的头部。
方法 2:自定义 BlockingQueue
实现
如果需要使用其他 BlockingQueue
实现类(如 ArrayBlockingQueue
),可以通过自定义实现来支持在头部插入元素。以下是一个简单的示例:
示例代码
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.Collection;
import java.util.NoSuchElementException;
public class CustomBlockingQueue<E> extends LinkedBlockingQueue<E> {
public CustomBlockingQueue() {
super();
}
public CustomBlockingQueue(int capacity) {
super(capacity);
}
public CustomBlockingQueue(Collection<? extends E> c) {
super(c);
}
// 自定义方法:将元素插入到队列头部
public void offerFirst(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
synchronized (this) {
while (this.size() == this.remainingCapacity()) {
wait();
}
super.offer(e); // 暂时添加到尾部
// 将尾部元素移动到头部
for (int i = 0; i < this.size() - 1; i++) {
super.offer(super.poll());
}
notifyAll();
}
}
public static void main(String[] args) throws InterruptedException {
CustomBlockingQueue<String> queue = new CustomBlockingQueue<>(10);
// 向队列尾部插入元素
queue.offer("Tail1");
queue.offer("Tail2");
// 向队列头部插入元素
queue.offerFirst("Head1");
queue.offerFirst("Head2");
// 打印队列内容
while (!queue.isEmpty()) {
System.out.println(queue.poll());
}
}
}
输出
Head2
Head1
Tail1
Tail2
说明
- 通过继承
LinkedBlockingQueue
,并添加offerFirst()
方法,实现将元素插入到队列头部。 - 在
offerFirst()
方法中,先将元素插入到队列尾部,然后通过循环将尾部元素移动到头部。
方法 3:使用 Collections.reverse()
反转队列
如果不需要实时插入到头部,可以先收集所有元素,然后反转队列。
示例代码
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
public class ReverseQueueExample {
public static void main(String[] args) {
BlockingQueue<String> queue = new LinkedBlockingQueue<>();
// 向队列插入元素
queue.offer("Element1");
queue.offer("Element2");
queue.offer("Element3");
// 将队列转换为列表并反转
List<String> list = new ArrayList<>(queue);
Collections.reverse(list);
// 打印反转后的队列
for (String element : list) {
System.out.println(element);
}
}
}
输出
Element3
Element2
Element1
说明
- 通过将队列转换为列表并反转,可以实现类似的效果。
- 这种方法适用于不需要实时操作队列的场景。
总结
- 如果需要实时将消息插入到队列头部,推荐使用
LinkedBlockingDeque
和offerFirst()
方法。 - 如果需要自定义
BlockingQueue
,可以通过继承和扩展实现。 - 如果不需要实时操作,可以使用
Collections.reverse()
反转队列。