对于定时器的设定,想必大家在不少网站或者文章中见到吧,但是所谓的定时器如何去用Java代码来bian'x呢??感兴趣的老铁,可以看一下笔者这篇文章哟~~
所谓的定时器就是闹钟!!
设定一个时间,当时间到,就可以执行一个指定的代码~
标准库提供的定时器Timer《——》在java.util包底下
Timer里内置了线程(前台线程),会阻止线程结束(代码运行后可见)
import java.util.Timer; import java.util.TimerTask; public class Main { public static void main(String[] args) { Timer timer =new Timer();//创建实列 timer.schedule(new TimerTask() { @Override public void run() { System.out.println("hello4"); } },4000);//4000毫秒后执行 timer.schedule(new TimerTask() { @Override public void run() { System.out.println("hello3"); } },3000);//3000毫秒后执行 timer.schedule(new TimerTask() { @Override public void run() { System.out.println("hello2" ); } },3000);//2000毫秒后执行 timer.schedule(new TimerTask() { @Override public void run() { System.out.println("hello1"); } },3000);//1000毫秒后执行 System.out.println("hello "); } }
上述代码的运行结果为:
在上述用到的:schedule:安排,安排一个工作,但不是立即完成,而是在未来某个时间点执行~
定时器应用场景非常多!尤其是网络编程~
超时是504
那么,如何自己实现一个定时器呢??
定时器内部关联的不仅仅是一个任务,可以管理很多任务的!!(比如:上面的代码),虽然任务可能有很多,他们的触发时间是不同的~
只要有一个/一组工作线程,每次都找到这些认为有最先到达时间的任务,当一个线程,先执行最早的任务,等做完了之后,在执行第二早的!时间到了就执行,时间没到就先等等!
定时器可能有多个线程在执行schedule方法!!希望在多线程下操作优先级队列,还能线程安全哈!!
PriorityBlockingQueue<>带有优先级的阻塞队列!
<>这里的元素需要我们手动封装一下里面的元素!
创建个类:表示两方面信息:
- 执行的任务是啥??
- 任务啥时候结束??
//描述任务的类 class MyTask implements Comparable<MyTask>{ private Runnable runnable;//描述要执行的任务 private long time;//什么时间执行,用时间戳来表示 public MyTask(Runnable task,long delay){ this.runnable = task; this.time = System.currentTimeMillis() + delay; } public Runnable getRunnable() { return runnable; } public long getTime() { return time; } @Override public int compareTo(MyTask o) { return (int) (this.getTime()-o.getTime()); } } //定时器 public class MyTimer { private BlockingQueue<MyTask> queue = new PriorityBlockingQueue<>(); Object locker = new Object(); public MyTimer(){ Thread t = new Thread(() -> { while (true){ synchronized (locker) { try { MyTask task = queue.take();//获取队首元素 long curTime = System.currentTimeMillis();//获取当前时间 //比较当前时间和队首元素的执行时间 if(curTime >= task.getTime()){ //时间到,执行任务 task.getRunnable().run(); }else { //时间没到,把元素再放回到队列中 queue.put(task); locker.wait(task.getTime() - curTime); } } catch (InterruptedException e) { e.printStackTrace(); } } } }); t.start(); } public void schedule(Runnable task,long delay) throws InterruptedException { MyTask myTask = new MyTask(task, delay); //把任务放入队列中 queue.put(myTask); synchronized (locker){ locker.notify(); } } }
可参考: