网站加密,教学管理信息服务平台,品牌管理,wordpress文章长上文讲了怎样使用Java自带的定时器【Java】定时器的简单应用
这篇博客就来讲如何来编写一个自己实现的定时器
1、代码框架
由定时器的使用方法得知#xff0c;我们在使用定时器的时候会添加一个任务timerTask类#xff0c;而timer类则是我们行使任务的类#xff0c;因此可…上文讲了怎样使用Java自带的定时器【Java】定时器的简单应用
这篇博客就来讲如何来编写一个自己实现的定时器
1、代码框架
由定时器的使用方法得知我们在使用定时器的时候会添加一个任务timerTask类而timer类则是我们行使任务的类因此可以得出我们需要编写的两个对象
一个timerTask类一个timer类
首先写下代码框架
class SelfTimerTask{}class SelfTimer{}public class demo {public static void main(String[] args) {}
} 2、SelfTimeTask类
这个类型用以存放我们要执行的任务
1成员变量
任务类中有两个成员一个是Runnable类用来存放要执行任务的内容一个是参数time用来存放执行任务的时间
为了防止内存可见性问题或指令重排序问题给这两个参数都加上volatile关键字
private volatile Runnable runnable;
private volatile long time;
2构造方法
接着我们需要给SelfTimerTask类写一个构造方法
注意上面成员变量time指的是任务执行的绝对时间而我们传进来的参数delay是任务执行的相对时间即此刻时间到任务执行绝对时间的差 任务执行的绝对时间 此刻时间 相对时间参数 public SelfTimerTask(Runnable runnable,long delay){this.runnable runnable;this.time delay System.currentTimeMillis();
}
3get方法
由于两个成员变量访问限制都为private所以我们需要写两个get方法
public Runnable getRunnable() {return runnable;
}public long getTime() {return time;
}
4compareTo方法
因为在任务执行时要通过比较任务的time参数来进行排序因此我们需要添加compareTo方法使SelfTimerTask类具有可比性
首先让类继承Comparable类
class SelfTimerTask implements ComparableSelfTimerTask
接着重写compareTo方法
public int compareTo(SelfTimerTask o) {return (int) (this.time - o.time);
}
注意这里到底谁减谁要根据后面的需求定可以根据调试来确定谁减谁
5SelfTimerTask完整代码
class SelfTimerTask implements ComparableSelfTimerTask {private volatile Runnable runnable;private volatile long time;public SelfTimerTask(Runnable runnable,long delay){this.runnable runnable;this.time delay System.currentTimeMillis();}Overridepublic int compareTo(SelfTimerTask o) {return (int) (this.time - o.time);}public Runnable getRunnable() {return runnable;}public long getTime() {return time;}
}
3、SelfTimer类
编写完SelfTimerTask类我们来编写SelfTimer类
SelfTimer类是用以按照时间先后顺序执行存储在其中的多个SelfTimerTask类中的任务的因此我们采用优先级队列的数据结构来编写SelfTimerTask类
定义一个优先级队列
PriorityQueueSelfTimerTask queue new PriorityQueue();
1schedule()方法
根据Timer类的使用可知SelfTimer有一个schedule()方法来添加任务
public void schedule(Runnable runnable,long time){SelfTimerTask task new SelfTimerTask(runnable,time);queue.offer(task);
}
由于下面有其他方法也要对queue进行操作为了线程安全我们在成员变量里定义一个locker对象
Object locker new Object();
并给添加任务这段代码加上锁
public void schedule(Runnable runnable,long time){SelfTimerTask task new SelfTimerTask(runnable,time);synchronized (locker){queue.offer(task);locker.notify();}
}
2SelfTimer()方法
因为在用schedule()方法添加任务后代码自动执行了任务因此我们需要在构造方法里书写一个线程来执行任务 public SelfTimer(){Thread thread new Thread(()-{});thread.start();}
下面来完善线程内代码内容
因为需要不停地扫描任务是否到了执行时间因此我们采用一个while循环
并且由于下面的代码对queue进行了操作我们需要加锁来保证线程安全
public SelfTimer(){Thread thread new Thread(()-{while (true){synchronized (locker){}}});thread.start();} · 大根堆还是小根堆
由于我们每次执行的是时间已经到达的任务那么这个任务的time参数一定是最小的
每次需要获取time最小的任务进行操作当然是选用小根堆
实现小根堆的方法就是重写类中的compareTo()方法上文已经阐述过这里不再赘述 · 队列为空
如果队列为空我们则需要进行阻塞一直到队列非空为止
另一方面为了防止线程是发生异常而被唤醒我们采用while循环进行判断
while (queue.isEmpty()){try {locker.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}
} · 执行任务
执行任务时首先判断现在的时间是否已经到达任务执行时间
若已经到了则执行任务若没有到就使任务再阻塞task.getTime()-curTime的时间
之所以选择阻塞是因为若这时队列中添加进了一个执行时间更靠前的任务可以唤醒对象重新开始循环
SelfTimerTask task queue.peek();
long curTime System.currentTimeMillis();
if (task.getTime() curTime){task.getRunnable().run();queue.poll();
}else {try {locker.wait(task.getTime()-curTime);} catch (InterruptedException e) {throw new RuntimeException(e);}
} 3SelfTimer完整代码
class SelfTimer{PriorityQueueSelfTimerTask queue new PriorityQueue();Object locker new Object();public void schedule(Runnable runnable,long time){SelfTimerTask task new SelfTimerTask(runnable,time);synchronized (locker){queue.offer(task);locker.notify();}}public SelfTimer(){Thread thread new Thread(()-{while (true){synchronized (locker){while (queue.isEmpty()){try {locker.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}}SelfTimerTask task queue.peek();long curTime System.currentTimeMillis();if (task.getTime() curTime){task.getRunnable().run();queue.poll();}else {try {locker.wait(task.getTime()-curTime);} catch (InterruptedException e) {throw new RuntimeException(e);}}}}});thread.start();}
}
4、完整代码
import java.util.PriorityQueue;class SelfTimerTask implements ComparableSelfTimerTask {private volatile Runnable runnable;private volatile long time;public SelfTimerTask(Runnable runnable,long delay){this.runnable runnable;this.time delay System.currentTimeMillis();}Overridepublic int compareTo(SelfTimerTask o) {return (int) (this.time - o.time);}public Runnable getRunnable() {return runnable;}public long getTime() {return time;}
}class SelfTimer{PriorityQueueSelfTimerTask queue new PriorityQueue();Object locker new Object();public void schedule(Runnable runnable,long time){SelfTimerTask task new SelfTimerTask(runnable,time);synchronized (locker){queue.offer(task);locker.notify();}}public SelfTimer(){Thread thread new Thread(()-{while (true){synchronized (locker){while (queue.isEmpty()){try {locker.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}}SelfTimerTask task queue.peek();long curTime System.currentTimeMillis();if (task.getTime() curTime){task.getRunnable().run();queue.poll();}else {try {locker.wait(task.getTime()-curTime);} catch (InterruptedException e) {throw new RuntimeException(e);}}}}});thread.start();}
}public class demo {public static void main(String[] args) {SelfTimer timer new SelfTimer();timer.schedule(new Runnable() {Overridepublic void run() {System.out.println(3000);}},3000);timer.schedule(new Runnable() {Overridepublic void run() {System.out.println(2000);}},2000);timer.schedule(new Runnable() {Overridepublic void run() {System.out.println(1000);}},1000);}
}运行结果