Java Timer 是Java 标准库中util包的一部分,是个简单易用的定时器。今天用到了顺便研究一下它的特点。
问题
- 疑问1:Timer用的什么线程?
- 疑问2: Timer周期执行时机,是从task启动开始算还是结束开始算?
测试代码
实验的代码:
import java.util.Timer;
import java.util.TimerTask;
public class T1 {
public static void main(String[] args) {
System.out.println("main start");
Timer timer = new Timer("Test timer");
timer.schedule(new TestTimerTask(), 10, 1000);
timer.schedule(new TestTimerTask(), 500, 1000);
System.out.println("\nmain end");
}
}
class TestTimerTask extends TimerTask {
private static int count = 0;
@Override
public void run() {
count ++;
System.out.print("\n" +Thread.currentThread().getName() + ": " + count + " start: " +System.currentTimeMillis() % 10000);
for (int i=0;i<10;i++) {
try {
Thread.sleep(20);
System.out.print('.');
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println(" end: " +System.currentTimeMillis() % 10000);
}
}
测试结果
解答疑问1:Timer用的什么线程?
Timer 会自己起一个线程,即使给它多个task也是一个线程。线程名字就是Time 构造时的名字。
另外,构造函数中也可以用布尔值指定这个线程是否是守护线程,如果指定是true,那么main函数停止时不会等timer结束;反之程序会等timer线程结束才停止。
解答疑问2:Timer周期执行时机,是从task启动开始算还是结束开始算?
一般情况下,Task执行时长小于一个周期长度,是从开始算,就是说假如schedule时指定每10秒执行一次,每次执行1秒钟,如timer.schedule(new TestTimerTask(), 0, 10000);
那么执行启动时间就是0秒,10秒,20秒…
注意:实验结果表明每次启动时间都不是严格等于周期,而是会延迟几毫秒,而且会累加。所以精确来说,上述启动时间可能是像这样:0.003秒,10.005秒,20.009秒…
但是如果Task执行时长大于一个周期的长度,那么当前工作做完已经超过了一个周期长度,比如上面别的条件不变但task每次要跑15秒,那么执行启动时间就会像这样: 0秒,15秒,30秒… 毕竟它是单线程的,需要干完一样再干一样…
Schedule 方式
public void schedule(TimerTask task, long delay)
public void schedule(TimerTask task, Date time)
public void schedule(TimerTask task, long delay, long period)
public void schedule(TimerTask task, Date firstTime, long period)
既可以指定首次启动延迟也可以知道首次运行具体日期时间。