学过数据结构的都应该知道,队列是什么,并且应该都知道队列最重要的特点是什么,实际上在Java中也是一样的,遵循这样的特点的,Java中的队列可以通过Java,util.Queue接口来实现,常见的队列实现包括java.util.linkedList和java.util.ArrayDeque。

Queue

Queue之Queue、BlockingQueue、AbstractQueue的相关知识介绍_java

Queue之Queue、BlockingQueue、AbstractQueue的相关知识介绍_System_02

队列的特点:

  • 先进先出: 队列遵循先进先出的原则,即先进入队列的元素将首先被移除。
  • 添加和移除操作: 队列提供了添加和移除元素的操作,通常使用offer()方法将元素添加到队列的尾部,使用poll()方法移除队列头部的元素。
  • 头部元素访问: 可以使用peek()方法获取队列头部的元素,而不会将其队列移除。
  • 队列大小: 可以使用size()方法获取队列中元素的数量。
  • 队列为空:可以使用isEmpty()方法检查队列是否为空。
  • 变量队列:可以使用迭代循环或者迭代器遍历队列中的元素。
  • 阻塞队列: java还提供特殊的队列实现,例如:java,util.concurrent.blockingQueue接口的实现类,用于多线程下的并发操作,这些队列提供了阻塞操作,可以在队列为空或者队列已满的时候阻塞队列。
public static void main(String[] args) {
        Queue<String> queue = new LinkedList<>();

        // 添加元素到队列
        queue.offer("Apple");
        queue.offer("Banana");
        queue.offer("Orange");

        // 获取队列头部元素
        String head = queue.peek();
        System.out.println("队列头部元素:" + head);

        // 移除队列头部元素
        String removedElement = queue.poll();
        System.out.println("移除的元素:" + removedElement);

        // 遍历队列中的元素
        System.out.println("队列中的元素:");
        for (String element : queue) {
            System.out.println(element);
        }
    }

BlockingQueue

Queue之Queue、BlockingQueue、AbstractQueue的相关知识介绍_ide_03

BlockingQueue是一个接口,它扩展了Queue接口,并提供了在队列为空或队列已满时阻塞线程的功能。BlockingQueue用于多线程环境下的并发操作,可以安全地在多个线程之间传递数据。

  • put(E element): 将元素添加到队列的尾部,如果队列已满,则阻塞线程直到队列有空间可用。
  • take(): 移除并返回队列头部的元素,如果队列为空,则阻塞线程直到队列有元素可用。
  • offer(E element, long timeout, TimeUnit unit): 将元素添加到队列的尾部,如果队列已满,则阻塞线程一段时间,超时后返回特定的结果。
  • poll(long timeout, TimeUnit unit): 移除并返回队列头部的元素,如果队列为空,则阻塞线程一段时间,超时后返回特定的结果。
  • size(): 返回队列中的元素数量。
  • 不接受null元素试图调用add,put,或者offer一个null元素时,某些实现会抛出NullPointerException。

Queue之Queue、BlockingQueue、AbstractQueue的相关知识介绍_System_04

BlockingQueue接口的常见实现类包括:

  • ArrayBlockingQueue: 基于数组的有界阻塞队列。
  • LinkedBlockingQueue: 基于链表的可选有界或无界阻塞队列。
  • PriorityBlockingQueue: 基于优先级的无界阻塞队列。
  • SynchronousQueue: 一个不存储元素的阻塞队列,用于线程间直接传递数据。
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class BlockingQueueExample {
    public static void main(String[] args) {
        BlockingQueue<String> queue = new LinkedBlockingQueue<>(3);

        // 生产者线程
        Thread producerThread = new Thread(() -> {
            try {
                queue.put("Apple");
                queue.put("Banana");
                queue.put("Orange");
                System.out.println("生产者线程已添加元素到队列");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        // 消费者线程
        Thread consumerThread = new Thread(() -> {
            try {
                Thread.sleep(2000); // 模拟消费者处理时间
                String element = queue.take();
                System.out.println("消费者线程已移除元素:" + element);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        producerThread.start();
        consumerThread.start();
    }
}

这个示例代码创建了一个LinkedBlockingQueue实例,设置队列的容量为3。然后,一个生产者线程向队列中添加3个元素,一个消费者线程从队列中移除一个元素。由于队列是阻塞的,消费者线程会等待生产者线程添加元素后再执行。

AbstractQueue

Queue之Queue、BlockingQueue、AbstractQueue的相关知识介绍_网络_05


Queue之Queue、BlockingQueue、AbstractQueue的相关知识介绍_System_06

AbstractQueue是一个抽象类,它实现了Queue接口的大部分方法,并提供了一些默认的实现。AbstractQueue为具体的队列实现类提供了一些通用的行为和方法。

  • add(E element): 将元素添加到队列的尾部,如果队列已满,则抛出异常。
  • offer(E element): 将元素添加到队列的尾部,如果队列已满,则返回false。
  • remove(): 移除并返回队列头部的元素,如果队列为空,则抛出异常。
  • poll(): 移除并返回队列头部的元素,如果队列为空,则返回null。
  • element(): 返回队列头部的元素,如果队列为空,则抛出异常。
  • peek(): 返回队列头部的元素,如果队列为空,则返回null。
  • isEmpty(): 检查队列是否为空。
  • size(): 返回队列中的元素数量。
import java.util.AbstractQueue;
import java.util.Iterator;
import java.util.LinkedList;

public class CustomQueue<E> extends AbstractQueue<E> {
    private LinkedList<E> queue = new LinkedList<>();

    @Override
    public boolean offer(E element) {
        return queue.offer(element);
    }

    @Override
    public E poll() {
        return queue.poll();
    }

    @Override
    public E peek() {
        return queue.peek();
    }

    @Override
    public Iterator<E> iterator() {
        return queue.iterator();
    }

    @Override
    public int size() {
        return queue.size();
    }

    public static void main(String[] args) {
        CustomQueue<String> queue = new CustomQueue<>();
        queue.offer("Apple");
        queue.offer("Banana");
        queue.offer("Orange");

        System.out.println("队列大小:" + queue.size());
        System.out.println("队列头部元素:" + queue.peek());

        System.out.println("遍历队列:");
        for (String element : queue) {
            System.out.println(element);
        }
    }
}

使用AbstractQueue来实现一个简单的任务调度器

import java.util.AbstractQueue;
import java.util.Iterator;
import java.util.concurrent.PriorityBlockingQueue;

public class TaskScheduler extends AbstractQueue<Task> {
    private PriorityBlockingQueue<Task> taskQueue = new PriorityBlockingQueue<>();

    @Override
    public boolean offer(Task task) {
        return taskQueue.offer(task);
    }

    @Override
    public Task poll() {
        return taskQueue.poll();
    }

    @Override
    public Task peek() {
        return taskQueue.peek();
    }

    @Override
    public Iterator<Task> iterator() {
        return taskQueue.iterator();
    }

    @Override
    public int size() {
        return taskQueue.size();
    }

    public static void main(String[] args) {
        TaskScheduler scheduler = new TaskScheduler();

        // 添加任务到调度器
        scheduler.offer(new Task("Task 1", 3));
        scheduler.offer(new Task("Task 2", 1));
        scheduler.offer(new Task("Task 3", 2));

        // 执行任务
        while (!scheduler.isEmpty()) {
            Task task = scheduler.poll();
            System.out.println("执行任务:" + task.getName());
            // 模拟任务执行时间
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Task implements Comparable<Task> {
    private String name;
    private int priority;

    public Task(String name, int priority) {
        this.name = name;
        this.priority = priority;
    }

    public String getName() {
        return name;
    }

    public int getPriority() {
        return priority;
    }

    @Override
    public int compareTo(Task other) {
        return Integer.compare(this.priority, other.priority);
    }
}

我们创建了一个TaskScheduler类,它继承了AbstractQueue类,并使用PriorityBlockingQueue作为内部的任务队列。Task类表示一个任务,它实现了Comparable接口,以便根据优先级进行排序。

在main方法中,我们创建了一个TaskScheduler实例,并添加了三个具有不同优先级的任务。然后,我们通过循环从调度器中取出任务并执行,模拟了任务调度的过程。