Java 中的 DelayQueue 和 ScheduledThreadPool 有什么区别?

Sherwin.Wei Lv7

Java 中的 DelayQueue 和 ScheduledThreadPool 有什么区别?

回答重点

DelayQueue 是一个阻塞队列,而 ScheduledThreadPool 是线程池,不过内部核心原理都是差不多的。

DelayQueue 是利用优先队列存储元素,当从队列中获取任务的时候,如果最老的任务已经到了执行时间,可以从队列中出队一个任务,反之可以获得 null 或者阻塞等待任务到时。

ScheduledThreadPool 内部也使用的一个优先队列 DelayedWorkQueue 且可以内部多线程执行任务,支持定时执行的任务,即每隔一段时间执行一次的任务。

扩展

DelayQueue 源码分析

首先,DelayQueue 中存储的所有元素必须实现 Delayed 接口,内部使用了优先级队列来存储元素,PriorityQueue 能保证优先级最高的元素优先出队。

image.png

添加元素

在添加元素的时候,会利用 ReentrantLock 上锁,实现添加元素的并发安全:

image.png

q.peek() 会返回优先级队列中最小的元素,这里的最小指的是延迟时间最短,最快需要执行的元素。

如果这个元素就是刚插入的元素,说明这个元素可能需要马上执行,因此立马通过 condition 的 signal 唤醒等待拿元素的线程。这个动作是为了确保队列的头部元素总是能够及时被处理

阻塞获取元素

take 方法的逻辑其实很简单,看下面的源码注解应该就很清晰了:

image.png

所以 DelayQueue 的本质就是使用了 PriorityQueue+lock+condition 来实现的。

DelayedWorkQueue 源码分析

实际上 DelayedWorkQueue 和 DelayQueue 几乎一模一样,差别就是 DelayedWorkQueue 没有使用 PriorityQueue 而是用 RunnableScheduledFuture 数组来实现了优先级队列,不过底层原理都是一样的。

我们来看下 take 方法,就能知道它们的实现没什么差别了:

image.png

所以 DelayedWorkQueue 的本质就是使用了 RunnableScheduledFuture+lock+condition 来实现的。

Comments