先来看DelayQueue继承了哪些类和实现了哪些接口:
DelayQueue是来源于java.util.concurrent包下面的一个类,DelayQueue属于集合中的一员,拥有集合的功能(Collection 接口存储一组不唯一,无序的对象,子类会扩展实现自己的方式),实现了BlockingQueue接口也属于阻塞队列中的一种,(阻塞这个词来自操作系统的线程/进程的状态模型中,阻塞调用是指调用结果返回之前,调用者会进入阻塞状态等待。只有在得到结果之后才会返回)。
然后我们就来看一下DelayQueue的UML图了解这个类的5大成员
1)ReentrantLock重入锁,将由最近成功获得锁,并且还没有释放该锁的线程所拥有。
2)PriorityQueue 一个基于优先级的无界优先级队列,用于存放需要延迟执行的元素。
3)Thread 指定线程等待在队列头部的元素,成员变量Thead leader设计出来是为了minimize unnecessary timed waiting(减少不必要的等待时间), 在DelayQueue中leader表示一个等待从队列中获取消息的线程。
4)Condition 接口提供一个线程挂起执行的能力,直到给定的条件为真。 Condition对象必须绑定到Lock,并使用newCondition()方法获取对象。
1)DelayQueue()
没有参数的构造器,仅仅是用来创建DelayQueue对象。
2)DelayQueue(Collection<? extends E> c)
初始化DelayQueue 并且将参数的集合元素通过offer方法添加到DelayQueue的成员变量PriorityQueue中,集合参数不能为空否则会报空指针异常。
1)public boolean add(E e)
public boolean add(E e) { return offer(e); } 复制代码
重写父类集合的方法 向延迟队列中插入元素,这里的实现方式是调用offer方法插入元素具体offer方法是怎么插入的可以看offer方法的实现。
2)public boolean offer(E e)
public boolean offer(E e) { final ReentrantLock lock = this.lock; lock.lock(); try { q.offer(e); if (q.peek() == e) { leader = null; available.signal(); } return true; } finally { lock.unlock(); } } 复制代码
重写父类Queue类的方法
流程如下:
3)public void put(E e)
public void put(E e) { offer(e); } 复制代码
4) public boolean offer(E e, long timeout, TimeUnit unit)
public boolean offer(E e, long timeout, TimeUnit unit) { return offer(e); } 复制代码
4) public E poll()
public E poll() { final ReentrantLock lock = this.lock; lock.lock(); try { E first = q.peek(); if (first == null || first.getDelay(NANOSECONDS) > 0) return null; else return q.poll(); } finally { lock.unlock(); } } 复制代码
流程如下:
public interface Delayed extends Comparable<Delayed> { /** * *给定时间返回元素 */ long getDelay(TimeUnit unit); } 复制代码
5) public E take() throws InterruptedException
public E take() throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { for (;;) { E first = q.peek(); if (first == null) available.await(); else { long delay = first.getDelay(NANOSECONDS); if (delay <= 0) return q.poll(); first = null; if (leader != null) available.await(); else { Thread thisThread = Thread.currentThread(); leader = thisThread; try { available.awaitNanos(delay); } finally { if (leader == thisThread) leader = null; } } } } } finally { if (leader == null && q.peek() != null) available.signal(); lock.unlock(); } } 复制代码
流程如下:
6)public E poll(long timeout, TimeUnit unit) throws InterruptedException
public E poll(long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { for (;;) { E first = q.peek(); if (first == null) { if (nanos <= 0) return null; else nanos = available.awaitNanos(nanos); } else { long delay = first.getDelay(NANOSECONDS); if (delay <= 0) return q.poll(); if (nanos <= 0) return null; first = null; if (nanos < delay || leader != null) nanos = available.awaitNanos(nanos); else { Thread thisThread = Thread.currentThread(); leader = thisThread; try { long timeLeft = available.awaitNanos(delay); nanos -= delay - timeLeft; } finally { if (leader == thisThread) leader = null; } } } } } finally { if (leader == null && q.peek() != null) available.signal(); lock.unlock(); } } 复制代码
*重写父接口BlockQueue中的方法:检索并删除此队列的头,如果需要,则等待指定的等待时间以使元素变为可用
流程如下
7)public E peek()
public E peek() { final ReentrantLock lock = this.lock; lock.lock(); try { return q.peek(); } finally { lock.unlock(); } } 复制代码
流程如下:
8) public int size()
public int size() { final ReentrantLock lock = this.lock; lock.lock(); try { return q.size(); } finally { lock.unlock(); } } 复制代码
流程如下:
9) public int drainTo(Collection<? super E> c)
public int drainTo(Collection<? super E> c) { if (c == null) throw new NullPointerException(); if (c == this) throw new IllegalArgumentException(); final ReentrantLock lock = this.lock; lock.lock(); try { int n = 0; for (E e; (e = peekExpired()) != null;) { c.add(e); // In this order, in case add() throws. q.poll(); ++n; } return n; } finally { lock.unlock(); } } 复制代码
流程如下:
private E peekExpired() { // assert lock.isHeldByCurrentThread(); E first = q.peek(); return (first == null || first.getDelay(NANOSECONDS) > 0) ? null : first; } 复制代码
10 )public int drainTo(Collection<? super E> c, int maxElements)
public int drainTo(Collection<? super E> c, int maxElements) { if (c == null) throw new NullPointerException(); if (c == this) throw new IllegalArgumentException(); if (maxElements <= 0) return 0; final ReentrantLock lock = this.lock; lock.lock(); try { int n = 0; for (E e; n < maxElements && (e = peekExpired()) != null;) { c.add(e); // In this order, in case add() throws. q.poll(); ++n; } return n; } finally { lock.unlock(); } } 复制代码
11) public void clear()
public void clear() { final ReentrantLock lock = this.lock; lock.lock(); try { q.clear(); } finally { lock.unlock(); } } 复制代码
12) public int remainingCapacity()
public int remainingCapacity() { return Integer.MAX_VALUE; } 复制代码
13) public Object[] toArray()
public Object[] toArray() { final ReentrantLock lock = this.lock; lock.lock(); try { return q.toArray(); } finally { lock.unlock(); } } 复制代码
14) public T[] toArray(T[] a)
public <T> T[] toArray(T[] a) { final ReentrantLock lock = this.lock; lock.lock(); try { return q.toArray(a); } finally { lock.unlock(); } } 复制代码
14) public boolean remove(Object o)
public boolean remove(Object o) { final ReentrantLock lock = this.lock; lock.lock(); try { return q.remove(o); } finally { lock.unlock(); } } 复制代码
15) public Iterator iterator()
public Iterator<E> iterator() { return new Itr(toArray()); } 复制代码
2.4 内部类
private class Itr implements Iterator<E> { final Object[] array; int cursor; int lastRet; Itr(Object[] array) { lastRet = -1; this.array = array; } public boolean hasNext() { return cursor < array.length; } @SuppressWarnings("unchecked") public E next() { if (cursor >= array.length) throw new NoSuchElementException(); lastRet = cursor; return (E)array[cursor++]; } public void remove() { if (lastRet < 0) throw new IllegalStateException(); removeEQ(array[lastRet]); lastRet = -1; } } 复制代码
3 DelayQueue的应用场景
1)DelayQueue应用场景,多考生考试问题
模拟一个考试: 考试时间为120分钟 30分钟后才可交卷 考试时间一到,所有未交卷的学生必须交卷 学生都交完卷了考试结束
2)关闭空闲连接。服务器中,有很多客户端的连接,空闲一段时间之后需要关闭之。
3)缓存。缓存中的对象,超过了空闲时间,需要从缓存中移出。
4)任务超时处理。在网络协议滑动窗口请求应答式交互时,处理超时未响应的请求。
5)模拟订单自动取消功能。
6)实现延时消息队列(简易版MQ)。
7)缓存系统的设计:可以用DelayQueue保存缓存元素的有效期,使用一个线程循环查询。 DelayQueue,一旦能从DelayQueue中获取元素时,表示缓存有效期到了。
8)定时任务调度:使用DelayQueue保存当天将会执行的任务和执行时间,一旦从DelayQueue中获取到任务就开始执行,比如TimerQueue就是使用DelayQueue实现的。
等等如果有更多应用场景或者实现可以一块交流。直接在聊天窗口回复消息即可。
String str = ""; System.out.print(str.split(",").length); 复制代码
输出结果为:(不要运行代码,猜你答不对)
答案可以关注微信公众号 拦截器 进行回复。