在Java的队列世界里,有三位大佬,他们分别是DelayQueue、PriorityQueue和PriorityBlockingQueue。今天,让我们一起揭开他们神秘的面纱,看看他们各自的特点和用途吧!

DelayQueue

Java基础 - 13 Queue之DelayQueue、PriorityQueue、PriorityBlockingQueue讲解_android

首先,让我们来认识一下DelayQueue。这位大佬有点“慢热”,因为他专门负责处理延迟任务。你可以把他想象成一个“倒计时专家”,只有在指定的延迟时间过后,任务才能被取出来。这在一些需要延迟执行的场景中非常有用,比如定时任务调度、缓存失效等。要使用DelayQueue,你需要实现Delayed接口,并重写getDelay()和compareTo()方法,让任务按照你的设定来执行。

Java基础 - 13 Queue之DelayQueue、PriorityQueue、PriorityBlockingQueue讲解_System_02

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;
    }

    @Override
    public long getDelay(TimeUnit unit) {
        long diff = delayTime - System.currentTimeMillis();
        return unit.convert(diff, TimeUnit.MILLISECONDS);
    }

    @Override
    public int compareTo(Delayed o) {
        return Long.compare(this.delayTime, ((DelayedElement) o).delayTime);
    }

    @Override
    public 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来定义元素的优先级顺序。这位大佬可是个“绅士”,总是把优先级最高的任务放在队列的最前面。

Java基础 - 13 Queue之DelayQueue、PriorityQueue、PriorityBlockingQueue讲解_开发语言_03

PriorityQueue 的特点和常用方法包括:

  • 默认情况下是一个小顶堆,也可以通过自定义 Comparator 来实现大顶堆。
  • 元素根据其自然顺序或者 Comparator 排序。
  • 插入操作和删除操作的时间复杂度为 O(log n)。
  • 不支持 null 元素。

常用方法包括:

  • add(E e) / offer(E e):将元素插入队列。
  • remove() / poll():获取并移除队列的头部元素。
  • peek():获取但不移除队列的头部元素。
  • size():返回队列的大小。

其他方法:

Java基础 - 13 Queue之DelayQueue、PriorityQueue、PriorityBlockingQueue讲解_开发语言_04


案例:

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());
        }
    }
}

Java基础 - 13 Queue之DelayQueue、PriorityQueue、PriorityBlockingQueue讲解_System_05

PriorityBlockingQueue

最后,让我们见识一下PriorityBlockingQueue,他是PriorityQueue的“大哥”,更加强大且安全。和PriorityQueue一样,他也是按照优先级来排序任务,但是在多线程环境下,PriorityBlockingQueue更加稳定可靠。他内部使用了可重入锁来保证线程安全,让你在多线程场景下也能够放心使用。如果你需要在多线程环境下处理优先级任务,PriorityBlockingQueue会是你的得力助手。

Java基础 - 13 Queue之DelayQueue、PriorityQueue、PriorityBlockingQueue讲解_开发语言_06

PriorityBlockingQueue 的特点和常用方法类似于 PriorityQueue,但是它是一个阻塞队列,支持生产者-消费者模型,具有以下特点:

  • 是一个无界队列,可以存储任意数量的元素。
  • 内部使用 ReentrantLock 来保证线程安全。
  • 支持自定义 Comparator 来定义元素的优先级。

常用方法包括:

  • put(E e):将元素插入队列,如果队列已满则阻塞等待。
  • take():获取并移除队列的头部元素,如果队列为空则阻塞等待。
  • offer(E e):将元素插入队列,如果成功则返回 true,否则返回 false。
  • poll():获取并移除队列的头部元素,如果队列为空则返回 null。

其他方法:

Java基础 - 13 Queue之DelayQueue、PriorityQueue、PriorityBlockingQueue讲解_System_07

案例:

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队列的世界里发挥着重要作用。