什么是 Java 的 Timer?

Sherwin.Wei Lv7

什么是 Java 的 Timer?

回答重点

Java 的 Timer 是一个用于调度任务的工具类,用于在未来某个时刻执行任务或周期性地执行任务。Timer 类一般与 TimerTask 搭配使用,其中 TimerTask 是一个需要执行的任务。

适用于简单的定时任务,如定时更新、定期发送报告等。

扩展知识

Timer 使用

TimerTaskTimer 需要执行的任务,它是一个实现了 Runnable 接口的抽象类,必须通过继承并实现其 run() 方法。

基本使用

  • 使用 Timer.schedule(TimerTask task, long delay) 在指定的延迟之后执行任务。
  • 使用 Timer.scheduleAtFixedRate(TimerTask task, long delay, long period) 周期性地执行任务。

示例代码

1
2
3
4
5
6
7
8
Timer timer = new Timer();
TimerTask task = new TimerTask() {
@Override
public void run() {
System.out.println("Task executed!");
}
};
timer.schedule(task, 2000); // 2 秒后执行任务

Timer 原理分析

Timer 可以实现延时任务,也可以实现周期性任务,它的核心就是一个优先队列和封装的执行任务的线程。

实现原理是:维持一个小顶堆,即最快需要执行的任务排在优先队列的第一个,根据堆的特性我们知道插入和删除的时间复杂度都是 O(logn)。

然后有个 TimerThread 线程不断地拿排着的第一个任务的执行时间和当前时间做对比。

如果时间到了先看看这个任务是不是周期性执行的任务,如果是则修改当前任务时间为下次执行的时间,如果不是周期性任务则将任务从优先队列中移除。最后执行任务。如果时间还未到则调用 wait() 等待。

可以看出 Timer 实际就是根据任务的执行时间维护了一个优先队列,并且起了一个线程不断地拉取任务执行。

Timer 有什么弊端呢?

首先优先队列的插入和删除的时间复杂度是O(logn),当数据量大的时候,频繁的入堆出堆性能有待考虑。

并且是单线程执行,那么如果一个任务执行的时间过久则会影响下一个任务的执行时间(当然你任务的run要是异步执行也行)。

并且从它对异常没有做什么处理,所以一个任务出错的时候会导致之后的任务都无法执行

ScheduledExecutorService

ScheduledExecutorService 是 Java 5 引入的替代方案,功能更强大。它支持多线程并行调度任务,能更好地处理任务调度的复杂场景。

因为使用线程池进行任务调度,所以不会因某个任务的异常终止而导致其他任务停止。并且它提供了更灵活的 API,可以更精细地控制任务的执行周期和策略。

推荐使用 ScheduledExecutorService 替代 Timer。

Comments