在Java的队列世界里,有三位大佬,他们分别是DelayQueue、PriorityQueue和PriorityBlockingQueue。今天,让我们一起揭开他们神秘的面纱,看看他们各自的特点和用途吧!
DelayQueue
首先,让我们来认识一下DelayQueue。这位大佬有点“慢热”,因为他专门负责处理延迟任务。你可以把他想象成一个“倒计时专家”,只有在指定的延迟时间过后,任务才能被取出来。这在一些需要延迟执行的场景中非常有用,比如定时任务调度、缓存失效等。要使用DelayQueue,你需要实现Delayed接口,并重写getDelay()和compareTo()方法,让任务按照你的设定来执行。
DelayQueue 是 Java 中的一个并发工具类,用于存储实现了 Delayed 接口的元素,并且这些元素会在一定时间之后才能被获取。常用于实现定时任务调度、消息延迟处理等场景。
在 DelayQueue 中,常用的方法包括:
put(E e):将指定元素放入队列中。
take():获取并移除队列的头部元素,如果队列为空,则阻塞等待。
poll():获取并移除队列的头部元素,如果队列为空,则返回 null。
offer(E e):将指定元素插入队列中,如果成功则返回 true,否则返回 false。
下面是一个简单的示例代码,演示了如何使用 DelayQueue:
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;class DelayedElement implements Delayed {private String data;private long delayTime;public DelayedElement(String data, long delayTime) {this.data = data;this.delayTime = System.currentTimeMillis() + delayTime;}@Overridepublic long getDelay(TimeUnit unit) {long diff = delayTime - System.currentTimeMillis();return unit.convert(diff, TimeUnit.MILLISECONDS);}@Overridepublic int compareTo(Delayed o) {return Long.compare(this.delayTime, ((DelayedElement) o).delayTime);}@Overridepublic String toString() {return data;}
}public class Main {public static void main(String[] args) throws InterruptedException {DelayQueue<DelayedElement> delayQueue = new DelayQueue<>();delayQueue.put(new DelayedElement("Element 1", 2000));delayQueue.put(new DelayedElement("Element 2", 5000));System.out.println("Elements added to queue");System.out.println(delayQueue.take());System.out.println(delayQueue.take());}
}
PriorityQueue
接下来,让我们迎接PriorityQueue,这位大佬可是“优先级之王”!他会根据元素的优先级来决定谁先出场,谁后登场。如果你有一堆任务,但又想要按照优先级来处理它们,PriorityQueue就是你的不二选择。你可以通过实现Comparable接口或者在构造函数中传入Comparator来定义元素的优先级顺序。这位大佬可是个“绅士”,总是把优先级最高的任务放在队列的最前面。
PriorityQueue 的特点和常用方法包括:
- 默认情况下是一个小顶堆,也可以通过自定义 Comparator 来实现大顶堆。
- 元素根据其自然顺序或者 Comparator 排序。
- 插入操作和删除操作的时间复杂度为 O(log n)。
- 不支持 null 元素。
常用方法包括:
- add(E e) / offer(E e):将元素插入队列。
- remove() / poll():获取并移除队列的头部元素。
- peek():获取但不移除队列的头部元素。
- size():返回队列的大小。
其他方法:
案例:
import java.util.PriorityQueue;public class Main {public static void main(String[] args) {PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();priorityQueue.offer(3);priorityQueue.offer(1);priorityQueue.offer(2);System.out.println("Elements in priority queue:");while (!priorityQueue.isEmpty()) {System.out.println(priorityQueue.poll());}}
}
PriorityBlockingQueue
最后,让我们见识一下PriorityBlockingQueue,他是PriorityQueue的“大哥”,更加强大且安全。和PriorityQueue一样,他也是按照优先级来排序任务,但是在多线程环境下,PriorityBlockingQueue更加稳定可靠。他内部使用了可重入锁来保证线程安全,让你在多线程场景下也能够放心使用。如果你需要在多线程环境下处理优先级任务,PriorityBlockingQueue会是你的得力助手。
PriorityBlockingQueue 的特点和常用方法类似于 PriorityQueue,但是它是一个阻塞队列,支持生产者-消费者模型,具有以下特点:
- 是一个无界队列,可以存储任意数量的元素。
- 内部使用 ReentrantLock 来保证线程安全。
- 支持自定义 Comparator 来定义元素的优先级。
常用方法包括:
- put(E e):将元素插入队列,如果队列已满则阻塞等待。
- take():获取并移除队列的头部元素,如果队列为空则阻塞等待。
- offer(E e):将元素插入队列,如果成功则返回 true,否则返回 false。
- poll():获取并移除队列的头部元素,如果队列为空则返回 null。
其他方法:
案例:
import java.util.concurrent.PriorityBlockingQueue;public class Main {public static void main(String[] args) throws InterruptedException {PriorityBlockingQueue<Integer> priorityBlockingQueue = new PriorityBlockingQueue<>();priorityBlockingQueue.put(3);priorityBlockingQueue.put(1);priorityBlockingQueue.put(2);System.out.println("Elements in priority blocking queue:");while (!priorityBlockingQueue.isEmpty()) {System.out.println(priorityBlockingQueue.take());}}
}
无论是“倒计时专家”DelayQueue、“优先级之王”PriorityQueue,还是“大哥”PriorityBlockingQueue,它们都各司其职,在Java队列的世界里发挥着重要作用。