前言:
关于定时器,我们日常生活中应用很多,比如空调,烤箱,微波炉或者一些手机软件等等都有定时功能,在我们设定的时间一到,它们就会自动关闭,这样为我们的生活提供了很多方便。在编程中也是同样的道理,在某些应用场合,需要定时地完成一些操作,希望能有一个“精准”定时的工具,方便编程。下面我们就来介绍一个简单的滴答滴答定时器。
思路:应该有一个线程,这个线程每经过一段时间(这个时间可以指定),就会“醒来”,并执行外部要求完成的操作。不管这个操作是否完成,只要时间片段一到,它就再次会去执行这个操作。
接下来我们看一下具体的代码。
SimpleDidaDida类:
public abstract class SimpleDidaDida implements Runnable{
private static final long DEFULT_DELAY = 1000;//默认时间
public long delay;
public volatile boolean goon;
private Object lock;
public SimpleDidaDida() {
this(DEFULT_DELAY);
}
public SimpleDidaDida(long delay) {
this.lock = new Object();
this.delay = delay;
}
public void start() {
if (goon == true) {
return;
}
goon = true;
new Thread(this).start();
}
public void stop() {
if (goon == false) {
return;
}
goon = false;
}
public abstract void doSomething();
@Override
public void run() {
while (goon) {
synchronized (lock) {
try {
lock.wait(delay);
new innerWorker();
} catch (InterruptedException e) {
goon = false;
}
}
}
}
private class innerWorker implements Runnable {
public innerWorker() {
new Thread(this).start();
}
@Override
public void run() {
doSomething();
}
}
}
从上面代码可以看出,我们开启一个线程专门去定时,再另外开启一个线程去完成一些外部要求完成的操作,即这个doSomething()方法。
DemoSimpleDidaDida类:
public class DemoSimpleDidaDida {
private SimpleDidaDida dida;
private int times = 0;
public DemoSimpleDidaDida() {
dida = new SimpleDidaDida(500) {
@Override
public void doSomething() {
int time = ++times;
try {
System.out.println("第" + time + "次开始时间:" + System.currentTimeMillis());
Thread.sleep(600);
System.out.println("第" + time + "次结束时间:" + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}
public void runup() {
dida.start();//开启定时器
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
dida.stop();//关闭定时器
}
}
测试类Test:
public class Test {
public static void main(String[] args) {
DemoSimpleDidaDida demo = new DemoSimpleDidaDida();
demo.runup();
}
}
测试结果:
第1次开始时间:1594963359981
第2次开始时间:1594963360412
第1次结束时间:1594963360644
第3次开始时间:1594963361048
第2次结束时间:1594963361134
第4次开始时间:1594963361479
第3次结束时间:1594963361660
第5次开始时间:1594963361989
第4次结束时间:1594963362083
第6次开始时间:1594963362532
第5次结束时间:1594963362612
第7次开始时间:1594963363081
第6次结束时间:1594963363143
第8次开始时间:1594963363556
第7次结束时间:1594963363691
第9次开始时间:1594963364109
第8次结束时间:1594963364189
第10次开始时间:1594963364586
第9次结束时间:1594963364726
第10次结束时间:1594963365231
从结果可以看出,第一次还没结束,第二次已经开始了。因为我们设置的定时时间是0.5秒,当0.5秒一到,就开始执行doSomething()方法。但是这个doSomething()方法不一定能在0.5秒内执行完。在doSomething()方法中,先输出开始时间,然后等待0.6秒,再输出结束时间。所以本次的这个方法还没执行完,下一次已经开始了。这充分体现了我们所写的定时器就是只起定时作用,它不会去管你在这个时间片段内到底能不能完成这个操作,只要时间一到,就执行这个方法。