四、Timer解析
Timer的基本使用流程
- 第一件事:new一个timer(计时器)
- 第二件事:定义一个任务TimerTask类【这里起名字为FooTimerTask】
- 包装一个定时任务:任务写在下面的一个类FooTimerTask(这个类需要继承TimerTask)
- 这个TimerTask实现了Runable接口(所以需要自己实现run()方法)。
- 在run()方法里写业务逻辑
- 模拟延时时间
- 定义一个变量
- 通过构造器来传入自己定义的日志名字
- Timer就两件事,然后就是启动项目了
- new一个对象
- 然后即使启动任务的方法
- schedule()
- scheduleAtFixedRate()
// 预设的执行时间nextExecutTime 12:00:00 12:00:02 12:00:04
//schedule 真正的执行时间 取决上一个任务的结束时间 ExecutTime 03 05 08 丢任务(少执行了次数)
//scheduleAtFixedRate 严格按照预设时间 12:00:00 12:00:02 12:00:04(执行时间会乱)
//单线程 任务阻塞 任务超时
Timer基本使用的缺点
- 该方法的缺点,不管你放多少任务,都是以单线程来运行的(源码里写的)。
- 单线程就会导致——任务阻塞,任务超时

解决单线程导致的任务阻塞,超时的方法:【正确的用法】
- 在TimerTask中的run()方法里面另起线程池【自己写】执行(这样就可以避免了)
使用场景:
- 必须是固定的时间,要不就是相对的时间。
- 每个月的一号执行就会做不到【严重依赖系统时间】。
代码展示:
- 需要使用就需要自己另起线程池,启动多线程
package com.tuling.timer;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
public static void main(String[] args) {
Timer t = new Timer();//任务启动
for (int i=0; i<2; i++){
TimerTask task = new FooTimerTask("foo"+i);
t.scheduleAtFixedRate(task,new Date(),2000);//任务添加 10s 5次 4 3
// 预设的执行时间nextExecutTime 12:00:00 12:00:02 12:00:04
//schedule 真正的执行时间 取决上一个任务的结束时间 ExecutTime 03 05 08 丢任务(少执行了次数)
//scheduleAtFixedRate 严格按照预设时间 12:00:00 12:00:02 12:00:04(执行时间会乱)
//单线程 任务阻塞 任务超时
}
}
}
class FooTimerTask extends TimerTask {
private String name;
public FooTimerTask(String name) {
this.name = name;
}
public void run() {
try {
System.out.println("name="+name+",startTime="+new Date());
Thread.sleep(3000);
System.out.println("name="+name+",endTime="+new Date());
//线程池执行
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
问题补充图:应用,任务调度,问题



本文介绍了Java Timer的使用,包括创建Timer、定义TimerTask,以及scheduleAtFixedRate和schedule的区别。提到了Timer的单线程缺点可能导致任务阻塞和超时,并给出了解决方案——在TimerTask中启动线程池进行多线程执行。适合于需要固定或相对时间执行的任务,但对依赖系统时间的场景不适用。示例代码展示了如何在实际应用中避免单线程问题。

被折叠的 条评论
为什么被折叠?



