丁岚-timer定时任务

简介: Timer是java.util提供的一个定时器,可以完成一些简单的定时任务,使用TimeTask以及Timer来实现

简介:

TimeTask是要执行的任务,Timer则是调度器

image.png

查看源码则能发现,TimerTask实现的Runnable接口,每次创建一个TimeTask就是创建了一个线程,再使用Timer来启动这个线程,控制这个任务什么时候执行,多久执行一次等。

任务调度

延迟调度

TimerTasktimerTask=newTimerTask() {

  @Override

  publicvoidrun() {

      System.out.println("延迟调度");

 }

};

Timertimer=newTimer();

timer.schedule(timerTask,2000);

这个便是启动后2s,调用TimeTask,延迟时间作为schedule的第二个参数传入进去,单位是毫秒,这个是只会调用一次

TimerTasktimerTask=newTimerTask() {

  @Override

  publicvoidrun() {

      System.out.println(Thread.currentThread().getName()+":"+"延迟多次调度");

 }

};

Timertimer=newTimer();

timer.schedule(timerTask,2000,1000);

而这个是启动后2s调用,之后每1s再次调用,第二个参数未延迟时间,第三个则为每隔多少时间再次调用,单位都是毫秒,这个可以调用多次。

指定时间调度

TimerTasktimerTask=newTimerTask() {

  @Override

  publicvoidrun() {

      System.out.println(Thread.currentThread().getName()+":"+"指定时间调度");

 }

};

Timertimer=newTimer();

longtime=System.currentTimeMillis()+5000;

Datedate=newDate(time);

timer.schedule(timerTask,date);

这个用法和上面延迟调度的用法基本类似,只是第二个参数为调度时间,到了指定的时间自动调度,若时间为过去时间, 则该任务会马上执行,并且不执行之前的任务,这个也是只执行一次,同样,在schedule的第三个参数,也是调用间隔。

TimerTasktimerTask=newTimerTask() {

  @Override

  publicvoidrun() {

      choose++;

      System.out.println(Thread.currentThread().getName()+":"+System.currentTimeMillis()+"延迟多次调度"+choose);

 }

};

Timertimer=newTimer();

longtimeMillis=System.currentTimeMillis()-5000;

timer.scheduleAtFixedRate(timerTask,newDate(timeMillis),1000L);

image.png

image.png

执行调度任可以使用scheduleAtFixedRateschedule两种方法,如果指定的时间为过去时间,那scheduleAtFixedRate则会将之前的任务一起执行,而schedule不会这样,但都是会立即执行。上面的运行结果则是一目了然,前面一张是使用的是scheduleAtFixedRate,在17:38:46运行调用任务时,一次运行了多个,将之前的任务也运行了,而第二张图却没有运行之前的任务。

任务精确性

TimerTasktimerTask=newTimerTask() {

  @Override

  publicvoidrun() {

      try {

          System.out.println("start");

          Thread.sleep(5000L);

          System.out.println(Thread.currentThread().getName()+":"+DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).format(ZonedDateTime.now())+"调度完成");

     } catch (InterruptedExceptione) {

          e.printStackTrace();

     }

 }

};

Timertimer=newTimer();

timer.schedule(timerTask,1000L,2000L);

image.png

从上面的运行结果可以看出,这个时候输出的结果并不是很准确,在上方,我们设置的是2s进行一次调用,但当我们在执行任务的时候,需要的时间超过了2s,那么,频率则不是所设置的时间,这样,就会导致所产生的结果和所预期的结果有误差。

ExecutorServiceexecutorService=Executors.newCachedThreadPool();

TimerTasktimerTask=newTimerTask() {

  @Override

  publicvoidrun() {

      executorService.execute(newRunnable() {

          @Override

          publicvoidrun() {

              try {

                  System.out.println("start"+newDate());

                  Thread.sleep(5000L);

             } catch (InterruptedExceptione) {

                  e.printStackTrace();

             }

         }

     });


 }

};

Timertimer=newTimer();

timer.schedule(timerTask,1000L,2000L);

image.png

这个时候就需要在执行的任务中,在开一个异步线程,这样就避免了,当调度这个任务之后,还需要等待任务完成才能进行下一次调度,从结果中看,这个时候已经是没2s进行一次任务调度,就和所期望的结果是一样的呢。

关闭任务

privatestaticintchoose=0;


publicstaticvoidmain(String[] args) {

      TimerTasktimerTask=newTimerTask() {

          @Override

          publicvoidrun() {

              choose++;

              System.out.println(Thread.currentThread().getName()+":"+"延迟多次调度"+choose);

         }

     };

      Timertimer=newTimer();

      timer.scheduleAtFixedRate(timerTask,2000L,500L);

      stop(timer);

}


publicstaticvoidstop(Timertimer){

  if (choose>8){

      timer.cancel();

 } else {

      try {

          Thread.sleep(1000);

          stop(timer);

     } catch (InterruptedExceptione) {

          e.printStackTrace();

     }

 }

}

当我们在开启调度任务后,可能在某种条件下需要关闭调度任务,就可以使用cancel方法,上面这段代码就是当choose大于八时,关闭调度任务,由于在下面那个递归中使用线程睡眠,可能主线程在睡眠时,调度任务执行了多次,使得choose并不是刚到九时就关闭,这里只是做一个演示。

相关文章
|
前端开发 算法 JavaScript
深入理解并解决 npm ERESOLVE (Peer Conflict) 问题
如果你持续使用 LTS 版本的 Node.js,或者主动更新了 npm 到 7+,一定见过下面这个难懂的报错: “unable to resolve dependency tree",字面意思就是无法解析依赖树,然后下面一大长串东西都在尝试告诉开发者无法解析的原因,并建议修复依赖间的冲突,但很尴尬的一点是……可能看了之后还是不知道,我要修复什么冲突呢?
7842 1
深入理解并解决 npm ERESOLVE (Peer Conflict) 问题
|
前端开发 JavaScript
React+Websocket简单实例
最近很多项目需要用到websocket,经过智能客服项目沉淀了一个简单的实例,以后可以直接用。有需要指教的地方可以联系我。
3639 0
|
2月前
|
Ubuntu Linux 网络安全
对时服务器技术教程:从配置到实战
本文参考http://gnifd.cn详解NTP对时服务器的配置与实战:涵盖Ubuntu下NTP服务部署、Python(ntplib)时间同步示例、常见问题排查(如服务启动失败、同步不准)、防火墙配置及进阶方向(分布式时间同步、安全性等),助力构建精准可靠的时间基础设施。(239字)
|
6月前
|
uml C语言
系统时序图
时序图是UML中描述对象间消息传递时间顺序的交互图,横轴为对象,纵轴为时间。用于展示交互流程、强调时序关系,直观呈现并发过程。主要元素包括角色、对象、生命线、控制焦点和消息等,广泛应用于系统动态建模。
系统时序图
|
监控 Ubuntu 网络协议
如何在 Ubuntu 16.04 上配置 NTP 以在 NTP Pool 项目中使用
如何在 Ubuntu 16.04 上配置 NTP 以在 NTP Pool 项目中使用
543 9
|
机器人 Python
ROS2教程 03 节点Node
本文是关于ROS2(机器人操作系统2)的教程,介绍了ROS2的节点概念、与ROS1的区别、节点的编写和基本流程、ros2的node相关命令,以及如何对节点名进行重映射,旨在帮助读者理解ROS2中节点的创建和操作。
1036 0
ROS2教程 03 节点Node
|
移动开发 网络协议 Linux
Linux系统中查看路由表的命令(ip route)
Linux系统中查看路由表的命令(ip route)
2631 0
|
前端开发 JavaScript 安全
Web前端开发中的三大主流框架
Web前端开发中的三大主流框架
|
算法
数学建模——曲线拟合
数学建模——曲线拟合
1980 1
|
缓存 分布式计算 并行计算
Python Joblib库使用学习总结
Python Joblib库使用学习总结
788 0