DelayQueue是一个无界阻塞队列,队列中元素只有在延迟期满时才能从中提取。在每次往优先级队列中添加元素时以元素的过期时间作为排序条件,最先过期的元素放在优先级最高。
DelayQueue实现的关键主要有如下几个:
- 可重入锁ReentrantLock
- 用于阻塞和通知的Condition对象
- 根据Delay时间排序的优先级队列:PriorityQueue(完全二叉堆)
- 用于优化阻塞通知的线程元素leader
DelayQueue的实现原理,个人理解如下概括:
操作一:获取最先过期元素
由于使用PriorityQueue数据结构,在添加元素时,最先过期的元素将一直放在优先级最高,即PriorityQueue的队头(详细请了解二叉堆数据结构),所以获取最先过期元素,即获取PriorityQueue的队头元素。
通过可重入锁ReentrantLock,筛选出一个获取元素的线程(假设线程A),如果此时元素已经过期则直接取得。
如果元素还未过期,还需要delay时间才到期,将线程A阻塞等待delay时间(通过条件对象Condition阻塞线程),时间到后则可以能够获取对头元素。
这里有个问题,由于线程A阻塞等待,所以锁将被释放,其他线程此时可以获取队头数据,也就是说,在线程A阻塞等待delay时间里,其他线程会不断的获取队头数据。如果它们也阻塞等待delay时间则有些多余,因为线程A已经在等待了,对于这种情况就是通过线程元素leader优化阻塞通知的线程