1. 计时器案例背景与核心需求
在Java多线程编程中,计时器(Timer)是一个经典且实用的场景。想象一下这样的需求:我们需要在某个固定时间后执行任务,或者周期性地重复执行某个操作。比如游戏中的技能冷却倒计时、电商平台的限时抢购倒计时、后台系统的定时数据备份等场景,都需要可靠的计时器实现。
Java本身提供了Timer和TimerTask类,但在多线程环境下直接使用它们会遇到不少坑。比如一个任务的执行时间过长会影响后续任务的触发,或者任务抛出异常导致整个计时器线程终止等问题。因此,我们需要自己实现一个更健壮的多线程计时器。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 计时器设计与核心组件
2.1 计时器架构设计
一个完整的计时器需要包含以下几个核心组件:
- 任务队列:用于存储待执行的任务,需要按照执行时间排序
- 调度线程:负责检查队列并执行到期任务
- 任务封装:将用户提交的Runnable和触发时间封装成统一格式
- 线程池:实际执行任务的线程资源
java复制// 基础任务封装类
class TimerTask {
private Runnable task;
private long executeTime;
public TimerTask(Runnable task, long delay) {
this.task = task;
this.executeTime = System.currentTimeMillis() + delay;
}
}
2.2 优先级队列的选择
任务队列需要频繁进行插入和获取最小时间的操作,因此我们选择PriorityQueue作为底层数据结构。为了保证线程安全,我们需要对其进行同步控制:
java复制private PriorityQueue<TimerTask> taskQueue =
new PriorityQueue<>(Comparator.comparingLong(t -> t.executeTime));
注意:PriorityQueue不是线程安全的,所有操作都需要在同步块内进行
