Java计时器
作用:
计时器也就是用来计时的东西。当你需要隔一段时间去干一件事的时候就可以用到它,比如:
当某拼夕夕网站的抢购在一段规定的时间内需要结束时。
比如某宝的页面需要在一段规定的时间里刷新页面时。
当你设置的闹钟在规定时间将你叫醒。
实现原理:
Thread.sleep(long millis);调用此方法可以让线程实现millis时间长度的睡眠。
代码显示:
package com.dxc.simple_dida.core.core;
public interface ISimpleDiDa {
void doSomething();
}
package com.dxc.simple_dida.core.core;
public class SimpleDiDa implements Runnable, ISimpleDiDa{
private long delayTime;
private boolean goon;//当goon为TRUE线程启动,为false线程关闭。
int count;
public SimpleDiDa() {
}
//设置线程休眠时间
public void setDelayTime(long delayTime) {
this.delayTime = delayTime;
}
//启动线程
public void startup() {
this.goon = true;
new Thread(this).start();
}
//计时器以规定的时间间隔
public void run() {
while (goon) {
try {
Thread.sleep(this.delayTime);
doSomething();//这里可以执行接口里面的方法
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//停止线程
public void stop() {
this.goon = false;
}
//设置接口方法实现的内容
//这里我输出一下时间,时间单位为毫秒
@Override
public void doSomething() {
System.out.println("第" + ++this.count
+ "次执行:" + System.currentTimeMillis());
}
}
测试代码:
package com.dxc.simple_dida.core.core;
public class Test {
public static void main(String[] args) {
SimpleDiDa sdd = new SimpleDiDa();
sdd.setDelayTime(1000); //设置线程执行时间间隔为一秒
sdd.startup();//启动线程
try {
Thread.sleep(10000);
//让主函数睡眠十秒钟,以便执行上面启动的线程
sdd.stop();//主函数休眠结束,关闭执行线程
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
测试结果
主函数休眠了十秒钟,所以线程执行了十次。每次线程执行的结果间隔应该为一秒,但结果我们可以看到第二次和第三次执行的结果间隔了1001毫秒。第六次和第七次间隔了1002毫秒。
在startup(),即,启动定时器时,令goon为真,并创建一个线程,这个线程处于死循环状态,以便能多次执行doSomething();
且,每次总是先休眠delayTime毫秒,再执行doSomething(),其实也就是每个delayTime毫秒,启动执行用户的任务。
但是,这个思路依然存在问题:因为sleep()方法之后执行了doSomething(),且,只有在doSomething()执行完毕后,才能进入下一轮计时,使得两次执行用户任务之间的时间间隔应该是:
delayTime + 用户任务所耗时间
上述错误的根本原因是:不应该在时间到达时执行用户任务,而是“启动”用户任务!在成功启动用户任务后,立刻继续重新计时!
这就要求,对于用户任务,应该再用一个线程执行之!
执行用户代码的接口
package com.dxc.senior_dida.core;
public interface ISeniorDiDa extends Runnable{
@Override
default void run() {
doSomething();
}
void doSomething();
}
package com.dxc.senior_dida.core;
public class SeniorDiDa implements Runnable {
public static final long DEFAULT_DELAY_TIME = 1000;
private long delayTime;
private volatile boolean goon;
private ISeniorDiDa worker;//用户执行的代码
public SeniorDiDa() {
this.delayTime = DEFAULT_DELAY_TIME;
}
//添加用户执行代码
public SeniorDiDa setWorker(ISeniorDiDa worker) {
this.worker = worker;
return this;
}
public SeniorDiDa setDelayTime(long delayTime) {
this.delayTime = delayTime;
return this;
}
//启动线程
public void startup() {
if (this.goon == true) {
return;
}
if (this.worker == null) {
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) {
try {
//线程睡眠delaytime时间
Thread.sleep(this.delayTime);
//线程睡眠期间,启动并执行用户要执行的代码
new Thread(this.worker).start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
测试代码
package com.dxc.senior_dida.core;
public class Test {
public static void main(String[] args) {
//设置用户要执行的代码
ISeniorDiDa worker = new ISeniorDiDa() {
private int count = 0;
@Override
public void doSomething() {
System.out.println("第" + ++this.count
+ "次执行:" + System.currentTimeMillis());
}
};
SeniorDiDa seniorDiDa = new SeniorDiDa()
.setWorker(worker);
seniorDiDa.startup();//启动线程
try {
Thread.sleep(10000);//主函数睡眠10000毫秒
seniorDiDa.stop();//线程停止
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}