任务执行时长比定时器的运行时间间隔更长,那么定时器的执行时间间隔将被拉长至任务执行的时长。比如,定时器定好2秒执行一次,但是任务执行需要花费3秒,那么实际上定时器是每3秒执行一次的。
定时器及main方法:
public static void main(String[] args) throws Exception {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
System.out.println("Time:" + format.format(new java.util.Date()));
System.out.println("Timer will start after 3 s.");
Timer timer = new Timer(); //统计定时器
timer.schedule(new TimerTask() {
@Override
public void run() {
new Test().printDate();
}
}, 0, 2000);
}
printDate方法:
public void printDate() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new java.util.Date()));
}
此时输出:
Time:2019-06-10 15:51:23.889
Timer will start after 3 s.
2019-06-10 15:51:26.893
2019-06-10 15:51:29.893
2019-06-10 15:51:32.893
2019-06-10 15:51:35.893
2019-06-10 15:51:38.893
Process finished with exit code 1
可以看到,任务实际上是每3秒执行一次的,这跟我们的预期是不相符的。
解决办法,在定时器任务的run方法中新建一个线程,让实际执行的任务在新线程中执行。此时,定时器任务的实际任务就是创建线程然后运行,线程运行后,任务就算结束了。耗时任务花费的时间算新线程的,跟定时器就没有关系了,这就规避了任务执行时长过长的问题。
修改后就变成:
timer.schedule(new TimerTask() {
@Override
public void run() {
new Thread(new Runnable() {
@Override
public void run() {
new Test().printDate();
}
}).start();
}
}, 0, 2000);
输出:
Time:2019-06-10 16:02:23.732
Timer will start after 3 s.
2019-06-10 16:02:26.738
2019-06-10 16:02:28.741
2019-06-10 16:02:30.743
2019-06-10 16:02:32.742
2019-06-10 16:02:34.742
2019-06-10 16:02:36.742
2019-06-10 16:02:38.742
Process finished with exit code 1
|