Java定时器的实现-------滴答滴答
今天我们来制作一个Java定时器
主要功能:使得一些需要固定间隔时间的事件能够如期执行
我们先来初步设计一下
对于要实现的事件,我们给一个接口
并且想到 对于主的线程(提供时延)以及 Timerworker线程
两个线程 通过抢占cpu 来实现定时
给一个线程 在里面进行 方法的执行 和 延时
我们分模块给出代码
git 滴答滴答 源码
构造方法:
public Dida(long delayTime,IDidaAction action ) {
this.lock=new Object();
// new 一个对象锁
this.action=action;
this.delayTime=delayTime;
}
核心代码:
@Override
public void run() {
while(goon)
synchronized(lock){
try {
lock.wait(delayTime);
// 先进行 等待 阻塞自己 将对象锁打开
lock.notify();
// 将下面线程唤醒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
TimeWorker:
class TimeWorker implements Runnable{
public void TimerWorker() {
}
@Override
public void run() {
while(goon) {
try {
synchronized(lock) {
lock.wait();
// 先将自己阻塞 对象锁打开
// 片段没到 则进行doSomething
// 到了则运行dida线程
}
action.doSomething();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// doSomething 每次的间隔时间是delayTime整数倍
// 因为 可能时间到了 但那个线程没准备好,就再进行一次等待
// 或者那个线程好了 但是 时间没到就 继续等等待时间完结
开始停止:
void start() {
if (action == null) {
System.out.println("无事可做!");
return;
}
if (goon) {
return;
}
goon = true;
new Thread(new TimeWorker(), "TimeWork").start();
new Thread(this, "DidaDida").start();
}
void stop() {
if (action == null) {
System.out.println("没做任何事!");
return;
}
if (goon == false) {
System.out.println("时钟已经停止计时!");
return;
}
goon = false;
}
// 先进行TimeWorker 然后 wait() 使得阻塞起来
// dida里面 wait delayTime
// 此时这两个线程都是阻塞的
// 直到 delayTime结束
// notify Timworker
// 从wait 下面开始执行开对象锁
// 执行 doSometing
// 并且继续执行 下一次执行
// 若是 doSomething 没执行完
// notify 此时无用 因为 根本没有线程处于阻塞 故会再次进行计时
最后new一个Dida类
实现dosomething()方法
然后给出开始 结束方法 之间要让主线程睡眠便于输出:
public static void main(String[] args) {
DidaDida dida = new DidaDida(50, new IDidaDidaAction() {
@Override
public void doSomething() {
System.out.println("\n---------------" + System.currentTimeMillis());
for (int i = 0; i < 10000000; i++) {
System.out.print(i);
}
}
});
dida.start();
try {
Thread.sleep(50000);
} catch (InterruptedException e) {
e.printStackTrace();
}
dida.stop();
System.out.println("停止!");
我们发现 这种情况下 :
当事件的执行时间比等待时间长时 我们是等待当前时间执行完才去执行下一个
于是我们就进行了改进
对于定时器里面我们当定时时间到的时候
另外开辟一个线程取执行
最后我们加上了线程池
这是改了之后的核心代码
@Override
public void run() {
while(goon) {
synchronized (lock) {
try {
lock.wait(delayTime);
new OtherWorker.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class OtherWorker extends Thread{
public OtherWorker() {
}
@Override
public void run() {
actionWorker.doSomething();
}
}
}