Timer
类是 Java 提供的用于执行定时任务的工具类。它允许你安排任务在未来的某个时间点执行,也可以定期执行。下面是关于Timer
类的详细介绍:
一、主要特点
-
任务调度:
Timer
类允许你调度指定的任务在将来的某个时间执行,或者按照一定的时间间隔循环执行。 -
单线程执行任务:
Timer
内部维护一个后台线程,用于执行任务。这意味着所有任务都是由同一个线程来串行执行的,因此如果一个任务执行时间过长,会影响其他任务的执行。 -
多任务支持:
Timer
允许你安排多个任务执行。 -
异常处理:
Timer
会捕获任务抛出的未捕获异常,防止这些异常中断任务队列的执行流程。
二、应用场景
-
定时任务调度:适用于需要在特定时间执行任务的场景,比如定时数据备份、定时数据清理等。
-
定期任务执行:适用于需要按照一定的时间间隔重复执行任务的场景,如定时发送心跳、定期执行某些操作等。
三、基本用法
要使用Timer
类执行定时任务,通常需要创建一个继承自TimerTask
类的任务,并在Timer
对象中安排任务的执行时间。例如:
import java.util.Timer;
import java.util.TimerTask;public class ScheduledTask extends TimerTask {@Overridepublic void run() {System.out.println("Task executed at: " + System.currentTimeMillis());}public static void main(String[] args) {Timer timer = new Timer();long delay = 1000; // 任务延迟1秒执行long interval = 2000; // 任务每隔2秒执行一次timer.scheduleAtFixedRate(new ScheduledTask(), delay, interval);}
}
注意事项
-
线程安全性:由于
Timer
是基于单个后台线程执行任务的,需要注意任务执行时间过长可能会影响其他任务的执行。 -
异常处理:需要留意捕获任务抛出的异常,以免异常中断任务队列的执行流程。
-
Java 5 之后的替代方案:虽然
Timer
类已经存在很长时间,但在 Java 5 中ScheduledThreadPoolExecutor
被引入,通常被认为是Timer
的更灵活、更可控制的替代方案。
四、自己实现
import java.util.PriorityQueue;public class MyTimer {//内部类表示创建的任务class Mytask implements Comparable<Mytask> {private Runnable runnable;// 为了⽅便后续判定, 使⽤绝对的时间戳.private long time;public Mytask(Runnable runnable, long delay) {this.runnable = runnable;// 取当前时刻的时间戳 + delay, 作为该任务实际执⾏的时间戳this.time = System.currentTimeMillis() + delay;}//表示每个任务以到达时间以小到大排序// 这样的写法意味着每次取出的是时间最⼩的元素.@Overridepublic int compareTo(Mytask o) {return (int)(this.time - o.time);}}// 核⼼结构private PriorityQueue<Mytask> queue = new PriorityQueue<>();// 创建⼀个锁对象private Object locker = new Object();//构造方法,创建线程Thread t;public MyTimer() {// 在这⾥构造线程, 负责执⾏具体任务了.t = new Thread( () -> {try {while (!Thread.currentThread().isInterrupted()) {synchronized (locker) {// 阻塞队列, 只有阻塞的⼊队列和阻塞的出队列, 没有阻塞的查看队⾸元素while (queue.isEmpty()) {locker.wait();}Mytask task = queue.peek();long waitTime = task.time - System.currentTimeMillis();if (waitTime <= 0) {// 时间到了, 可以执⾏任务了queue.poll();task.runnable.run();} else {// 时间还没到locker.wait(waitTime);}}}}catch (InterruptedException e) {e.printStackTrace();}});t.start();}public void schedule(Runnable command, long after) {synchronized (locker) {Mytask mytack = new Mytask(command, after);//根据参数,插入队列queue.offer(mytack);locker.notify();}}//中断线程public void cancel() {t.interrupt();for (Mytask task : queue) {queue.remove(task);}}// 测试代码public static void main(String[] args) {MyTimer timer = new MyTimer();timer.schedule( ()->{System.out.println(2000);}, 2000);timer.schedule( () -> {System.out.println(1000);}, 1000);timer.schedule( ()->{System.out.println(3000);}, 3000);System.out.println(100);}
}