【复习】Java中常见的几种队列
前言
本文不讲具体结构,只粗略讲解如何使用
经常看看、防止遗忘
代码
/**
* @Author if
* @Description: 【复习】Java中常见的几种队列
* @Date 2022-02-25 下午 07:12
*/
public class QueueTest {
public static void main(String[] args) {
/**
* 普通队列,默认0容量
* 所有类型的Queue队列都拥有add与remove会抛异常,offer与poll不抛异常的特点
*/
Queue<Integer> queue=new LinkedList<>();
//元素入队出队,失败的时候会抛出异常(不推荐)
queue.add(2);
System.out.println("queue.remove() = " + queue.remove());
//元素入队出队,失败的时候不会抛出异常(推荐)
queue.offer(1);
System.out.println("queue.poll() = " + queue.poll());
/**
* 双端队列,ArrayDeque容量默认16,LinkedList容量默认0
*/
Deque<Integer> arrayDeque = new ArrayDeque<>();
Deque<Integer> linkedList = new LinkedList<>();
//元素添加到队首
arrayDeque.offerFirst(3);
arrayDeque.offerFirst(5);
arrayDeque.offerFirst(1);
//输出队首与队尾的元素
System.out.println("arrayDeque.pollFirst() = " + arrayDeque.pollFirst());
System.out.println("arrayDeque.pollLast() = " + arrayDeque.pollLast());
/**
* 阻塞队列,ArrayBlockingQueue必须给初始值,LinkedBlockingQueue默认Integer.MAX_VALUE
*/
BlockingQueue<Integer> arrayBlockingQueue = new ArrayBlockingQueue<>(5);
BlockingQueue<Integer> linkedBlockingQueue = new LinkedBlockingQueue<>();
//队列空或满时,将抛出异常的添加与删除
arrayBlockingQueue.add(1);
arrayBlockingQueue.remove();
//队列空或满时,不抛异常且有返回值
arrayBlockingQueue.offer(2);
arrayBlockingQueue.poll();
try{
//队列空或满时,将一直阻塞等待
arrayBlockingQueue.put(3);
arrayBlockingQueue.take();
//队列空或满时,阻塞等待一定时间后会自动放弃等待
arrayBlockingQueue.offer(4,5,TimeUnit.SECONDS);
arrayBlockingQueue.poll(5,TimeUnit.SECONDS);
}catch(Exception e){
e.printStackTrace();
}
/**
* 优先队列,默认容量11,默认递增顺序(n1,n2)->n1-n2。这里写的倒序(n1,n2)->n2-n1
*/
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>((n1,n2)->n2-n1);
priorityQueue.offer(3);
priorityQueue.offer(4);
priorityQueue.offer(2);
System.out.println("priorityQueue = " + priorityQueue);
/**
* 延时队列,需要一个继承了Delay类并重写了compareTo与getDelay方法的的消息类,并将其添加到队列中
*/
DelayQueue<Message> delayQueue = new DelayQueue<>();
//添加延时消息m1与m2,分别延时3s与5s
Message m1 = new Message(1, "hello", 3000);
Message m2 = new Message(2, "world", 5000);
//将延时消息放到延时队列中
delayQueue.offer(m1);
delayQueue.offer(m2);
//开启线程进行消费
new Thread(()->{
int size = delayQueue.size();
for (int i = size; i > 0; i--) {
try {
Message message = delayQueue.take();
System.out.println("message.getBody() = " + message.getBody());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
/**
* @Author if
* @Description: 延迟队列——消息体
* 实现Delayed接口就是实现两个方法即compareTo 和 getDelay
* 最重要的就是getDelay方法,这个方法用来判断是否到期
* @Date 2022-02-25 下午 07:12
*/
static class Message implements Delayed {
private int id;
// 消息内容
private String body;
// 延迟时长,这个是必须的属性。因为要按照这个判断延时时长。
private long executeTime;
// 自定义实现比较方法返回 1 0 -1三个参数
@Override
public int compareTo(Delayed delayed) {
Message msg = (Message) delayed;
return Integer.compare(this.id, msg.id);
}
// 延迟任务是否到期执行,就是按照这个方法判断,如果返回的是负数则说明到期否则还没到期
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(this.executeTime - System.nanoTime(), TimeUnit.NANOSECONDS);
}
public String getBody() {
return body;
}
public Message(int id, String body, long delayTime) {
this.id = id;
this.body = body;
this.executeTime = TimeUnit.NANOSECONDS.convert(delayTime, TimeUnit.MILLISECONDS) + System.nanoTime();
}
}
}