化妆培训网站模板,无锡网站制作价格多少,711相卡打印网址,网站怎么做成小程序目录 一、定时器简介1.1 Timer类1.2 使用案例 二、实现简易定时器2.1 MyTimerTask类2.2 实现schedule方法2.3 构造方法2.4 总代码2.5 测试 一、定时器简介
定时器#xff1a;就相当于一个闹钟#xff0c;当我们定的时间到了#xff0c;那么就执行一些逻辑。
1.1 Timer类
… 目录 一、定时器简介1.1 Timer类1.2 使用案例 二、实现简易定时器2.1 MyTimerTask类2.2 实现schedule方法2.3 构造方法2.4 总代码2.5 测试 一、定时器简介
定时器就相当于一个闹钟当我们定的时间到了那么就执行一些逻辑。
1.1 Timer类
Java的标准库中提供了在java.util包下的Timer类作为定时器。 有如下的构造方法 四种
timer() 无参构造timer(boolean isDaemon) 创建的线程都是后台线程timer(String name) 给定时器中创建的线程名字timer(String name, boolean isDaemon) 创建的线程都是后台线程也给定时器中创建的线程名字。
在Timer类中的核心方法是schedule方法。
schedule(Timer task, Date time) 到达time时刻后执行task任务schedule(Timer task, Date firstTime, long period) 到达time时刻后重复执行task任务每次相隔period时间schedule(Timer task, long delay) 在delay时间后执行task任务schedule(Timer task, long delay, long period) 在delay时间后重复执行task任务每次相隔period时间scheduleAtFixedRate(Timer task, Date firstTime, long period) 到达time时刻后重复执行task任务每次执行period时间scheduleAtFixedRate(Timer task, long delay, long period) 在delay时间后重复执行task任务每次执行period时间
schedule的第一个参数是TimerTask类这是一个实现了Runnable接口的抽象类。
1.2 使用案例
我们使用schedule方法来打印不同时间执行不同内容。
import java.util.Timer;
import java.util.TimerTask;public class Demo {public static void main(String[] args) {Timer timer new Timer();timer.schedule(new TimerTask() {Overridepublic void run() {System.out.println(3000ms后执行);}},3000);timer.schedule(new TimerTask() {Overridepublic void run() {System.out.println(1000ms后执行);}},1000);timer.schedule(new TimerTask() {Overridepublic void run() {System.out.println(2000ms后执行);}},2000);}
}结果如下会按照等待时间由小到大打印内容并且执行完之后并不会结束这是因为这些线程是前台线程。
二、实现简易定时器
自己实现的定时器主要要考虑下面几个内容
设计一个类表示任务对应TimerTask类使用优先级队列来组织多个任务每次根节点都是等待时间最短的任务实现schedule方法把任务添加到队列中额外创建一个线程负责执行队列中的任务根据时间来执行即判断是否到了该执行的时间了。
2.1 MyTimerTask类
这个类中需要
将要执行的任务和任务要执行的时刻记录下来并且这个任务还要有通过时刻比较得方法即实现Comparator接口重写CompareTo方法便于后面存储进优先级队列。
代码
class MyTimerTask implements ComparableMyTimerTask{//记录任务private Runnable task null;//记录执行任务的时刻private long current 0;public MyTimerTask(Runnable task, long current) {this.task task;this.current current;}public Runnable getTask() {return task;}public long getCurrent() {return current;}Overridepublic int compareTo(MyTimerTask o) {return (int)(this.current - o.current);}
}2.2 实现schedule方法
我们实现schedule方法
只需要将当前的任务传入队列中即可。将参数Runnable的任务和时刻用来创建MyTimerTask类在入队即可。我们还要使用notify为后面的线程中因为队列为空调用wait进入阻塞状态提供唤醒。
代码
private PriorityQueueMyTimerTask queue new PriorityQueue();public void schedule(Runnable task, long delay) {synchronized (this) {MyTimerTask myTimerTask new MyTimerTask(task, System.currentTimeMillis() delay);queue.offer(myTimerTask);this.notify();}}2.3 构造方法
在构造方法中额外创建一个线程负责执行队列中的任务根据时间来执行即判断是否到了该执行的时间了。
我们在最外层使用一层死循环来不断去读取队列中的任务。如果队列空了那么我们就出这次循环但是如果使用continue的话还是会在循环的去判断直到队列不为空为止。这样的消耗很高我们可以使用wait等待schedule方法入队列后来唤醒这个线程。如果没有到达执行时间我们也要出这次循环但是使用continue也会导致在从现在这个时刻到执行时刻之间一直进行无意义的执行上面的代码消耗很高我们这里直接使用带参数的wait方法等待还需要的时间即可。到达执行时间直接执行任务并出队列即可。最后不要忘记启动这个线程。
代码
public MyTimer() {Thread thread new Thread(()- {try {while(true) { //循环拿任务直到任务队列为空synchronized (this) {while (queue.isEmpty()) { //任务队列为空this.wait();}MyTimerTask task queue.peek();if(task.getCurrent() System.currentTimeMillis()) { //没到执行时间 this.wait(task.getCurrent() - System.currentTimeMillis());} else {task.run();queue.poll();}}}} catch (InterruptedException e) {e.printStackTrace();}});thread.start();}2.4 总代码
总代码如下
class MyTimerTask implements ComparableMyTimerTask{//记录任务private Runnable task null;//记录执行任务的时刻private long current 0;public MyTimerTask(Runnable task, long current) {this.task task;this.current current;}public Runnable getTask() {return task;}public long getCurrent() {return current;}Overridepublic int compareTo(MyTimerTask o) {return (int)(this.current - o.current);}public void run() {task.run();}}class MyTimer {private PriorityQueueMyTimerTask queue new PriorityQueue();public void schedule(Runnable task, long delay) {synchronized (this) {MyTimerTask myTimerTask new MyTimerTask(task, System.currentTimeMillis() delay);queue.offer(myTimerTask);this.notify();}}public MyTimer() {Thread thread new Thread(()- {try {while(true) { //循环拿任务直到任务队列为空synchronized (this) {while (queue.isEmpty()) { //任务队列为空this.wait();}MyTimerTask task queue.peek();if(task.getCurrent() System.currentTimeMillis()) { //没到执行时间this.wait(task.getCurrent() - System.currentTimeMillis());} else {task.run();queue.poll();}}}} catch (InterruptedException e) {e.printStackTrace();}});thread.start();}
}2.5 测试
如果在main中执行下面这样的代码也使用schedule方法来打印不同时间执行不同内容会与上面使用案例的结果一样。
public static void main(String[] args) {MyTimer timer new MyTimer();timer.schedule(new Runnable() {Overridepublic void run() {System.out.println(3000ms后执行);}},3000);timer.schedule(new Runnable() {Overridepublic void run() {System.out.println(1000ms后执行);}},1000);timer.schedule(new Runnable() {Overridepublic void run() {System.out.println(2000ms后执行);}},2000);}结果如下会按照等待时间由小到大打印内容并且执行完之后并不会结束这是因为这些线程是前台线程。