先来看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);
复制代码
输出结果为:(不要运行代码,猜你答不对)
答案可以关注微信公众号 拦截器 进行回复。