苏州住房城乡建设部网站wordpress 加载失败
- 作者: 五速梦信息网
- 时间: 2026年04月20日 08:24
当前位置: 首页 > news >正文
苏州住房城乡建设部网站,wordpress 加载失败,深圳网站系统建设,网站建设部门宣言定时器概念 当我们不需要某个线程立刻执行#xff0c;而是在指定时间点或指定时间段之后执行#xff0c;假如我们要定期清理数据库里的一些信息时#xff0c;如果每次都手动清理的话就太麻烦#xff0c;所以就可以使用定时器。定时器就可以比作一个闹钟#xff0c;可以让…定时器概念 当我们不需要某个线程立刻执行而是在指定时间点或指定时间段之后执行假如我们要定期清理数据库里的一些信息时如果每次都手动清理的话就太麻烦所以就可以使用定时器。定时器就可以比作一个闹钟可以让我们的线程在指定的时间执行还可以指定时间循环执行。 标准库中的定时器 在标准库中提供了一个Timer类Timer是一种定时器工具可以让一个线程在指定时间一次或反复执行。 Timer的构造方法 Timer()Timer(String name)设定定时器的名字Timer(boolean isDeamon)是否将定时器作为守护线程Timer(String name,boolean isDeamon)设定定时器名字并设定是否为守护线程执行 非守护线程JVM会等待所有非守护线程执行完毕之后才会退出 守护线程JVM不会等待守护线程执行完毕当没有非守护线程在执行JVM就会关闭即使 有守护线程在执行 TimerTask是一个抽象类表示的是一个可以被timer执行的任务任务的具体实现在TimerTask的run方法里。 schedule方法是Timer中的核心方法用来执行TimerTask的任务并设定时间具体的参数有以下几种 schedule(TimerTask taskDate time); 在time时间(时间点)执行任务一次 schedule(TimerTask tasklong delay); 在delay时间后执行任务一次(单位毫秒) schedule(TimerTask taskDate firstTimelong period); 在firstTime时间点执行一次任务在定期的period时间段后反复执行(如果时间点是已经过去的时间就会立刻执行) schedule(TimerTask tasklong delaylong period); 在延迟delay毫秒后执行任务一次在定期的period时间段后反复执行(如果时间点是已经过去的时间就会立刻执行) 定时器的使用 在指定时间段后执行 public static void main(String[] args) {Timer timer new Timer();//对象被创建时线程也跟着被创建后续timer执行任务都是由这个线程执行//给定时器安排一个任务xxxms后执行timer.schedule(new TimerTask() {Overridepublic void run() {System.out.println(开始执行定时器任务);}},1000);System.out.println(执行任务);} 主线程执行schedule方法的时候就是把这个任务放到timer对象中了与此同时timer里头也有一个线程叫做“扫描线程”一旦时间到扫描线程就会执行刚才安排的任务了仔细观察可以发现整个线程其实没有结束就是因为Timer内部的线程阻止了进程的结束而且在timer里是可以安排多个任务的这些任务会按照时间顺序执行。(也就是我们刚刚说过的非守护线程给timer设置成守护线程此时整个线程就会结束了) 在指定时间点执行 public static void main(String[] args) {Timer timer new Timer();//对象被创建时线程也跟着被创建后续timer执行任务都是由这个线程执行//给定时器安排一个任务xxxms后执行//获取5秒后的一个时间点doTimeCalendar calCalendar.getInstance();cal.add(Calendar.SECOND,5);Date doTimecal.getTime();timer.schedule(new TimerTask() {Overridepublic void run() {System.out.println(开始执行定时器任务 new Date());}},doTime);System.out.println(new Date());} 在指定时间段后定期循环执行 public static void main(String[] args) {Timer timer new Timer();//对象被创建时线程也跟着被创建后续timer执行任务都是由这个线程执行//给定时器安排一个任务xxxms后执行timer.schedule(new TimerTask() {Overridepublic void run() {System.out.println(开始执行定时器任务 new Date());}},2000,1000);System.out.println(new Date());} 在指定时间点后定期循环执行 public static void main(String[] args) {Timer timer new Timer();//对象被创建时线程也跟着被创建后续timer执行任务都是由这个线程执行//给定时器安排一个任务xxxms后执行//获取5秒后的一个时间点doTimeCalendar calCalendar.getInstance();cal.add(Calendar.SECOND,5);Date doTimecal.getTime();timer.schedule(new TimerTask() {Overridepublic void run() {System.out.println(开始执行定时器任务 new Date());}},doTime,1000);System.out.println(new Date());} 定时器的实现 这里我们来简单实现一个定时器 初步分析 Timer中要有一个扫描线程线程扫描任务是否到时间可以执行了需要一种数据结构来储存这些任务还需要创建一个类来描述一个任务要包含内容和时间 先来考虑使用什么数据结构来储存任务既然Timer中的任务是从时间最小的开始执行那么我们就可以使用优先级队列 实现 MyTimerTask 一个执行的任务至少要包含任务内容和执行的时间这里我用的是绝对时间当要判断一个线程是否需要执行时先获取一个当前的时间戳(2:30)在获取任务要执行的时间戳(2:35)最后对比两个时间戳就知道现在是否要执行任务。 但是我们刚刚有提到要使用优先级队列来存储任务所以我们还要有一个任务的比较规则我们要让队列知道该怎么比 所以完整的代码如下 class MytimerTask implements ComparableMytimerTask{//要执行的任务private Runnable runnable;//要执行任务的绝对时间private long time;public MytimerTask(Runnable runnable,long time){this.runnable runnable;//此处this.time是应该开始执行任务的时间time是多久后执行this.time System.currentTimeMillis() time;}//任务的比较规则Overridepublic int compareTo(MytimerTask o) {return (int)(this.time - o.time);}public Runnable getRunnable() {return runnable;}public long getTime() {return this.time;} } MyTimer 定义一个优先级队列实现schedule方法 private PriorityQueueMytimerTask queue new PriorityQueue();public void schedule(Runnable runnable,long time){ //向队列里插入一个任务以及过多久后执行该任务queue.offer(new MytimerTask(runnable,time));} 实现扫描线程 private Object locker new Object();public MyTimer(){//创建一个扫描线程Thread t new Thread(() - {//扫描线程需要不停扫描队首元素看是否到达时间while (true){try {synchronized (locker){//使用while是为了在wait被唤醒的时候再次确认一下条件while (queue.isEmpty()){//这里的wait需要有另外线程唤醒//添加新的任务就应该唤醒locker.wait();}MytimerTask task queue.peek();//比较一下当前的队首元素就是最近一个要执行的任务是否可以执行了long curtime System.currentTimeMillis();if(curtime task.getTime()){//当时间到达任务时间就可以执行任务了task.getRunnable().run();//任务执行完之后在队列中删除queue.poll();}else {//还没到任务时间暂时不执行任务locker.wait(task.getTime() - curtime);}}}catch (InterruptedException e){e.printStackTrace();break;}}});t.start();} 因为我们需要不断的判断队列里的线程是否到达时间所以使用while循环 因为当前可能会是在多线程下使用所以我们要保证线程安全问题使用synchronization来进行加锁 如果队列为空的话就需要阻塞等待直到有新的任务加入所以schedule方法应该这样实现 public void schedule(Runnable runnable,long time){synchronized (locker){//向队列里插入一个任务以及过多久后执行该任务queue.offer(new MytimerTask(runnable,time));//当队列为空时此时插入一个任务之后唤醒waitlocker.notify();}} 这里还有一个问题 因为while的执行速度很快如果让他一直不断的循环就会造成忙等问题(在消耗cpu资源但是并没有实质性的用处)假如最近一个要执行的任务是十分钟之后那么从现在开始的十分钟之内while是没有执行的必要的不停的循环只会浪费资源。 所以我们可以进行判断当还没有到最近一个任务执行时间时我们就让线程阻塞阻塞的时间就是现在到最近一个要执行的任务的时间这样就可以解决忙等问题。 那么可不可以使用sleep呢当然是不行的。 可能在等待过程中主线程调用schedule又添加一个新任务这个任务比其他任务执行的时间更早使用wait就恰好可以利用刚才schedule中的notify来唤醒这里的wait让循环再执行一遍重新拿到队首执行时间最少的任务 之所以刚刚的代码使用的是PriorityQueue而不是PriorityBlockingQueue其实就是因为要处理两个wait的地方使用阻塞版本的优先级队列不方便实现。 完整代码如下 class MytimerTask implements ComparableMytimerTask{//要执行的任务private Runnable runnable;//要执行任务的绝对时间private long time;public MytimerTask(Runnable runnable,long time){this.runnable runnable;//此处this.time是应该开始执行任务的时间time是多久后执行this.time System.currentTimeMillis() time;}//任务的比较规则Overridepublic int compareTo(MytimerTask o) {return (int)(this.time - o.time);}public Runnable getRunnable() {return runnable;}public long getTime() {return this.time;} } //自己的定时器 class MyTimer{private PriorityQueueMytimerTask queue new PriorityQueue();public void schedule(Runnable runnable,long time){synchronized (locker){//向队列里插入一个任务以及过多久后执行该任务queue.offer(new MytimerTask(runnable,time));//当队列为空时此时插入一个任务之后唤醒waitlocker.notify();}}private Object locker new Object();public MyTimer(){//创建一个扫描线程Thread t new Thread(() - {//扫描线程需要不停扫描队首元素看是否到达时间while (true){//开始进行一次扫描try {synchronized (locker){//使用while是为了在wait被唤醒的时候再次确认一下条件while (queue.isEmpty()){//这里的wait需要有另外线程唤醒//添加新的任务就应该唤醒locker.wait();}MytimerTask task queue.peek();//比较一下当前的队首元素就是最近一个要执行的任务是否可以执行了long curtime System.currentTimeMillis();if(curtime task.getTime()){//当时间到达任务时间就可以执行任务了task.getRunnable().run();//任务执行完之后在队列中删除queue.poll();}else {//还没到任务时间暂时不执行任务locker.wait(task.getTime() - curtime);}}}catch (InterruptedException e){e.printStackTrace();break;}}});t.start();} } 到这里一个简单的定时器就完成了 测试 public static void main(String[] args) {MyTimer timer new MyTimer();timer.schedule(new Runnable() {Overridepublic void run() {System.out.println(3000 new Date());}},3000);timer.schedule(new Runnable() {Overridepublic void run() {System.out.println(2000 new Date());}},2000);timer.schedule(new Runnable() {Overridepublic void run() {System.out.println(1000 new Date());}},1000);System.out.println(启动程序);} 以上就是博主对定时器知识的分享如果有不懂的或者有其他见解的欢迎在下方评论或者私信博主也希望多多支持博主之后和博客
相关文章
-
苏州制作网站的有几家快递企业网站建设设计方案范例
苏州制作网站的有几家快递企业网站建设设计方案范例
- 技术栈
- 2026年04月20日
-
苏州制作网站的公司网站怎么做描文本
苏州制作网站的公司网站怎么做描文本
- 技术栈
- 2026年04月20日
-
苏州制作公司网站的沧州市网站优化排名
苏州制作公司网站的沧州市网站优化排名
- 技术栈
- 2026年04月20日
-
苏州资讯网站建设wordpress文章尾部
苏州资讯网站建设wordpress文章尾部
- 技术栈
- 2026年04月20日
-
苏州做网站的单位杭州市下城区建设局门户网站
苏州做网站的单位杭州市下城区建设局门户网站
- 技术栈
- 2026年04月20日
-
苏州做网站好的公司html 网站链接
苏州做网站好的公司html 网站链接
- 技术栈
- 2026年04月20日
