一、Timer
public static void main(String[] args) {
// 内部维护的一个堆
Timer timer = new Timer();
// 3s后开始执行 每1s执行一次
long s = System.currentTimeMillis();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("timer ....");
}
}, 3000,1000);
}
1.1 内部源码
// 优先级队列
private final TaskQueue queue = new TaskQueue();
// 线程
private final TimerThread thread = new TimerThread(queue);
核心是一个优先级队列和一个封装执行任务的线程。大致逻辑如下:内部维持了一个小顶堆,按时间排序,最近要执行的任务排在第一个。不断获取第一个判断当前是否需要执行。
- 需要执行如果是周期任务 修改下次执行时间 否则await()
![image.png](https://img-blog.csdnimg.cn/img_convert/c7d2a9a5d3aea0ba4d5c65b2b15ad8b6.png#averageHue=#fcfcfb&clientId=u3a59141f-86a3-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=598&id=u187653f1&margin=[object Object]&name=image.png&originHeight=1196&originWidth=1342&originalType=binary&ratio=1&rotation=0&showTitle=false&size=453902&status=done&style=none&taskId=u484b2f4e-f48f-46f8-b4f9-d42a3ca1a77&title=&width=671)
void add(TimerTask task) {
// Grow backing store if necessary
if (size + 1 == queue.length)
queue = Arrays.copyOf(queue, 2*queue.length);
// 添加到数组末尾
queue[++size] = task;
// 调整堆
fixUp(size);
}
队列的插入和删除的时间复杂度Ologn
二、DelayQueue
jdk自带的一个延迟队列工具,元素必须实现delay接口底层内部也是通过 Priority优先级队列实现。
2.1 内部源码
public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
implements BlockingQueue<E> {
private final transient ReentrantLock lock = new ReentrantLock();
// 底层还是依赖PriorityQueue 优先级队列实现
private final PriorityQueue<E> q = new PriorityQueue<E>();
重写take方法通过 delay获取延迟时间。
- 是Leader/Followers模式:
三、ScheduledThreadPool
可以执行定时任务的线程池
public class ScheduledThreadPoolExecutorDemo {
public static void main(String[] args) {
// 延迟定时任务
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(5);
// 延迟1s后执行 步长1s
executor.scheduleAtFixedRate(()->{
System.out.println("ScheduledThreadPoolExecutorDemo..");
}, 1,1, TimeUnit.SECONDS);
}
}
3.1 内部源码
// 实现了 ScheduledExecutorService
public class ScheduledThreadPoolExecutor
extends ThreadPoolExecutor
implements ScheduledExecutorService {
// 底层构造了一个 DelayedWorkQueue 也是一个优先级队列,内部是小顶堆
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
public void run() {
// 周期性任务
boolean periodic = isPeriodic();
if (!canRunInCurrentRunState(periodic))
cancel(false);
else if (!periodic)
ScheduledFutureTask.super.run();
else if (ScheduledFutureTask.super.runAndReset()) {
// 设置下次执行时间
setNextRunTime();
// 任务重入队列
reExecutePeriodic(outerTask);
}
}