BlockingQueue---DelayQueue
总结
一个无界阻塞队列;
FIFO;
只包含实现了 Delayed
接口的元素,每个元素都有一个延迟时间,在该延迟时间结束之前,该元素不会从队列中可用。一旦元素的延迟到期,它就可以被取出了,并且取出的顺序是按照延迟到期的时间先后进行的。
通常用于实现定时任务调度、缓存过期等场景。例如,可以用来管理超时连接或自动删除过期的数据。
特性
- 无界:可以容纳任意数量的元素。
- 基于延迟:元素只有在其延迟时间到期后才可被取出。
- 线程安全:支持多线程同时进行插入和移除操作。
- 阻塞:取元素的操作(如
take()
)如果在没有延迟到期的元素时会被阻塞,直到有元素的延迟到期。
构造函数
DelayQueue()
: 创建一个新的 DelayQueue
实例。
方法
-
插入操作:
put(E e)
: 将指定的延迟元素插入此队列。由于DelayQueue
只接受实现了Delayed
接口的对象,所以这里的E
必须是Delayed
类型。offer(E e)
: 尝试将指定的延迟元素插入此队列。与put
方法类似,但不会抛出异常。
-
移除操作:
take()
: 检索并移除此队列的头(其延迟已过的元素),如果队列为空,则等待有元素可用。poll()
: 检索并移除此队列的头(其延迟已过的元素),如果队列为空,则立即返回null
。poll(long timeout, TimeUnit unit)
: 检索并移除此队列的头(其延迟已过的元素),如果队列为空,则最多等待指定的时间,如果超时队列仍然为空则返回null
。
-
检查操作:
peek()
: 检索但不移除此队列的头(其延迟已过的元素);如果队列为空,则返回null
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | public class DelayQueue<E extends Delayed> extends AbstractQueue<E> implements BlockingQueue<E> { private final transient ReentrantLock lock = new ReentrantLock(); private final PriorityQueue<E> q = new PriorityQueue<E>(); public DelayQueue() {} 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(); } } 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 class PriorityQueue<E> extends AbstractQueue<E> implements java.io.Serializable { private static final int DEFAULT_INITIAL_CAPACITY = 11; transient Object[] queue; private int size = 0; private final Comparator<? super E> comparator; public PriorityQueue() { this (DEFAULT_INITIAL_CAPACITY, null ); } public PriorityQueue( int initialCapacity, Comparator<? super E> comparator) { // Note: This restriction of at least one is not actually needed, // but continues for 1.5 compatibility if (initialCapacity < 1) throw new IllegalArgumentException(); this .queue = new Object[initialCapacity]; this .comparator = comparator; } public boolean offer(E e) { if (e == null ) throw new NullPointerException(); modCount++; int i = size; if (i >= queue.length) grow(i + 1); size = i + 1; if (i == 0) queue[0] = e; else siftUp(i, e); return true ; } public E poll() { if (size == 0) return null ; int s = --size; modCount++; E result = (E) queue[0]; E x = (E) queue[s]; queue[s] = null ; if (s != 0) siftDown(0, x); return result; } } |
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | static class DelayedElement implements Delayed { private final long delayTime; // 延迟时间 private final long expire; // 到期时间 private final String name; // 元素名称 public DelayedElement( long delay, String name) { this .delayTime = delay; this .name = name; this .expire = System.nanoTime() + TimeUnit.NANOSECONDS.convert(delay, TimeUnit.MILLISECONDS); } @Override public long getDelay(TimeUnit unit) { return unit.convert(expire - System.nanoTime(), TimeUnit.NANOSECONDS); } @Override public int compareTo(Delayed other) { if ( this == other) { return 0; } if (other instanceof DelayedElement) { DelayedElement otherDE = (DelayedElement) other; return Long.compare( this .expire, otherDE.expire); } long diff = getDelay(TimeUnit.NANOSECONDS) - other.getDelay(TimeUnit.NANOSECONDS); return (diff < 0) ? -1 : (diff > 0) ? 1 : 0; } @Override public String toString() { return "DelayedElement{" + "name='" + name + '\ '' + ", delay=" + delayTime + "ms" + '}' ; } } public static void main(String[] args) throws InterruptedException { DelayQueue<DelayedElement> queue = new DelayQueue<>(); // 添加一些延迟元素 queue.put( new DelayedElement(1000, "One" )); queue.put( new DelayedElement(500, "Two" )); queue.put( new DelayedElement(2000, "Three" )); // 消费者线程 Thread consumer = new Thread(() -> { try { while ( true ) { DelayedElement element = queue.take(); System. out .println( "Consumed: " + element); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); consumer.start(); // 等待一段时间以观察输出 Thread.sleep(3000); consumer.interrupt(); // 停止消费者 // 结果: // Consumed: DelayedElement{name='Two', delay=500ms} //Consumed: DelayedElement{name='One', delay=1000ms} //Consumed: DelayedElement{name='Three', delay=2000ms} } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
2019-09-20 《计算机组成原理》---运算方法与运算器
2019-09-20 《计算机组成原理》---计算机中数据信息的表示
2019-09-20 《计算机组成原理》---概论