一、Timer支持并行处理
java.util.Timer类的作者是大名鼎鼎的Josh Bloch,他可是Java集合框架的作者,谷歌首席架构师。最近一直想研究定时任务,所以就从最最古老的类开始使用吧。
从API文档里看到一个延迟的方法,就是延迟执行任务。我这里的每个任务都是打印任务名称。但是延迟的时间从5秒递减到1秒。运行结果是什么呢?
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(getRandomTask(5), 5000);
timer.schedule(getRandomTask(4), 4000);
timer.schedule(getRandomTask(3), 3000);
timer.schedule(getRandomTask(2), 2000);
timer.schedule(getRandomTask(1), 1000);
}
private static TimerTask getRandomTask(int num) {
TimerTask task = new TimerTask() {
@Override
public void run() {
System.out.println("任务" + num);
}
};
return task;
}
从运行结果来看,看来Timer类内部很可能维护了一个"任务队列",并且知道这个任务在具体得某一刻开始执行。延迟最小的任务1只延迟了1秒,所以第一个打印出来。相反,任务5虽然在主函数的第一行执行,但是延迟5秒后才最后打印出来。所以可以确定,一个Timer对象能够执行多个任务。
拨云见日
Timer类的执行是支持多线程并行处理的。
二、再谈Timer类异常处理
下面的代码几乎与上面得相同,只是在构造任务的时候加了一个限制,就是说如果执行了任务3会出错。运行结果又会是什么呢?
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(getRandomTask(5), 5000);
timer.schedule(getRandomTask(4), 4000);
timer.schedule(getRandomTask(3), 3000);
timer.schedule(getRandomTask(2), 2000);
timer.schedule(getRandomTask(1), 1000);
}
private static TimerTask getRandomTask(int num) {
TimerTask task = new TimerTask() {
@Override
public void run() {
System.out.println("任务" + num);
if (num == 3) {
String error = "任务" + num + "报错";
throw new RuntimeException(error);
}
}
};
return task;
}
我把本次运行结果与上次运行结果拿出来对比一下。任务3报错,实际上就会让本该执行的任务4与任务5执行不了。换句话说,Timer类在多线程并行处理任务的时候,只要其中一个定时任务出错,那么其它任务也都会自动停止运行。这在生产库上是绝对不允许的。或许这也是Timer被废弃的重要缺陷之一吧。
本次程序运行结果:
上次程序运行结果
拨云见日
Timer类在执行多个任务的时候,如果其中一个任务出错,并且没有捕获异常的话,其它任务也会终止执行。所以为了防止这种情况的出现,需要为每个任务使用try--catch语句。