1. 计时器项目概述
在Java多线程编程中,计时器(Timer)是一个经典且实用的案例。这个看似简单的功能背后,其实涉及线程调度、任务队列、同步控制等多个核心知识点。我曾在电商平台的订单超时取消功能中实现过一个生产级计时器,今天就来拆解这个案例的技术实现。
计时器的本质是一个延迟任务执行器,它需要具备以下核心能力:
- 在指定延迟时间后执行任务
- 支持周期性重复执行任务
- 能够高效管理大量定时任务
- 保证线程安全性和执行可靠性
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心设计思路
2.1 计时器架构设计
一个完整的计时器通常包含三个核心组件:
- 任务队列:使用优先级队列(PriorityQueue)存储待执行任务,按执行时间排序
- 工作线程:负责从队列中取出到期任务并执行
- 调度器:处理任务添加、取消等操作,协调线程工作
java复制class Timer {
private final PriorityQueue<TimerTask> taskQueue;
private final TimerThread workerThread;
// ...
}
2.2 任务队列实现关键点
任务队列需要满足以下特性:
- 线程安全:多线程环境下添加/取出任务不会出现竞态条件
- 高效调度:能快速获取最近要执行的任务
- 阻塞等待:当没有到期任务时,线程能够合理休眠
使用PriorityQueue配合ReentrantLock实现:
java复制private final PriorityQueue<TimerTask> taskQueue =
new PriorityQueue<>(Comparator.comparing(TimerTask::getExecutionTime));
private final ReentrantLock lock = new ReentrantLock();
private final Condition newTaskAvailable = lock.newCondition();
2.3 时间调度算法
计时器的核心调度逻辑采用"等待-通知"机制:
- 工作线程检查队列头部任务
- 如果任务已到期,立即执行
- 如果未到期,计算等待时间并休眠
- 新任务到达时唤醒线程重新检查
java复制long currentTime = System.currentTimeMillis();
TimerTask task = taskQueue.peek();
if (task == null) {
newTaskAvailable.await();
} else {
long executionTime = task.getExecutionTime();
if (executionTime <= currentTime) {
// 执行任务
} else {
long waitTime = executionTime - currentTime
