需求:在某些应用场合,需要定时地完成一些操作,希望能有一个“精准”定时的工具,方便编程。
应该有一个线程,这个线程每经过一段时间(这个时间可以指定),就“醒来”,并执行外部要求完成的操作。
需求分析:
由于要实现一个定时器,还要执行用户的方法,理所应当应该专门用一个线程来进行定时,并放到一个循环里面,但是是否需要再来一个线程专门进行方法的执行,需要进行斟酌。
如果不再单独调用一个线程话,那么代码将会是如下形式:
@Override
public void run() {
while (goon) {
synchronized (lock) {
try {
lock.wait(delay);
// TODO 这里执行用户提供的方法
} catch (InterruptedException e) {
goon = false;
}
}
}
}
但是,我们不知道用户的代码的复杂度,如果用户的代码很庞大,那么一定会影响我们的定时效果,因为我们需要执行完用户的代码,才能进行下一轮的定时。显然这种方式是不合理的。
我们还可以单独给一个线程来执行用户的代码,两个线程之间,互不影响,一个专门定时,一个专门执行代码,不论用户的代码有多么复杂,我们都可以精确定时。
代码如下:
//这里实现了Runnable接口
public abstract class SimpleDidaDida implements Runnable {
// 默认的定时间隔
public static final long DEFAULT_DELAY = 1000;
private long delay;
// 这里的goon必须进行寄存器优化。详解请看博文:
[volatile关键字](https://blog.csdn.net/weixin_44836233/article/details/102688559)
private volatile boolean goon;
private Object lock;
// 提供多种方式供用户调用
public SimpleDidaDida() {
this(DEFAULT_DELAY);
}
// 用户可以输入定时的间隔,若不输入则调用默认的时间间隔。
public SimpleDidaDida(long delay) {
this.lock = new Object();
this.delay = delay;
}
// 抽象方法,方便用户可以自己实现
public abstract void doing();
// 开始启动定时器
public void start() {
if (this.goon == true) {
return;
}
this.goon = true;
// 启动一个线程,用一个线程来专门定时
new Thread(this).start();
}
// 关闭定时器
public void stop() {
if (this.goon == false) {
return;
}
this.goon = false;
}
// 这个方法图样图森破
@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() {
doing();
}
}
}
当然也有其他方法实现,例如开启一个线程,也可以采用继承的方式;用户提供的方法也可以采用先创捷一个默认的接口,将该接口类型作为一个成员,用户需调用定时器前,需要设置该接口效果和写抽象方法类似。
由此,我的工具包又增加了一个工具,方便以后的使用。