丁岚-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并不是刚到九时就关闭,这里只是做一个演示。

相关文章
|
NoSQL Java 关系型数据库
蚂蚁金服+拼多多+抖音+天猫(技术三面)面经合集助你拿大厂offer
很多Java开发者面试之前,可能没有较长的工作时间或者较为丰富的工作经验,所以不知道互联网公司或者一线互联网公司技术面试都会问哪些问题? 再加上可能自己准备也不充分,去面试没几个回合就被面试官几个问题打蒙了,最后以惨败收场。针对这些的读者朋友,小编整理了一些知名大厂的面经,在这分享给读者朋友们参考,让即将面试或是有想法跳槽的读者朋友们了解一下一线大厂面试时都喜欢问那些问题。
|
6月前
|
机器学习/深度学习 人工智能 算法
Stable Virtual Camera:2D秒变3D电影!Stability AI黑科技解锁无限运镜,自定义轨迹一键生成
Stable Virtual Camera 是 Stability AI 推出的 AI 模型,能够将 2D 图像转换为具有真实深度和透视感的 3D 视频,支持自定义相机轨迹和多种动态路径,生成高质量且时间平滑的视频。
300 0
Stable Virtual Camera:2D秒变3D电影!Stability AI黑科技解锁无限运镜,自定义轨迹一键生成
|
10月前
在 onerror 事件处理函数中停止接收数据
【10月更文挑战第26天】关闭 WebSocket 连接后,客户端将不再接收来自服务器的数据,同时服务器端也会收到连接关闭的通知。在实际应用中,需要根据具体的业务场景和错误处理需求来选择合适的方法来停止接收数据,以确保应用程序的稳定性和数据的一致性。
|
11月前
|
机器学习/深度学习 自然语言处理 语音技术
RNN是什么?哪些地方应用的多?
【10月更文挑战第8天】RNN是什么?哪些地方应用的多?
654 0
|
11月前
|
监控 Java 数据库
Spring事务中的@Transactional注解剖析
通过上述分析,可以看到 `@Transactional`注解在Spring框架中扮演着关键角色,它简化了事务管理的复杂度,让开发者能够更加专注于业务逻辑本身。合理运用并理解其背后的机制,对于构建稳定、高效的Java企业应用至关重要。
357 0
|
弹性计算 人工智能 自然语言处理
诚云科技招聘进行中!
诚云科技招聘进行中!
3388 2
|
弹性计算 固态存储 调度
2024年阿里云服务器配置选择指南,新手整理
阿里云服务器配置选择指南:个人用户推荐轻量应用服务器或ECS通用算力型u1,适合小型网站和轻量应用。企业用户应选择企业级独享型如ECS计算型c7、通用型g7,保证高性能计算需求。配置选择要考虑CPU内存比例、公网带宽和系统盘。轻量服务器提供2核2G3M和2核4G4M选项,ECS实例则有多种规格以适应不同业务场景。公网带宽建议至少5M,系统盘可选高效云盘、SSD或ESSD。详细信息见[阿里云服务器产品页](https://www.aliyun.com/product/ecs)。
1213 3
|
监控 小程序 Java
《优化接口设计的思路》系列:第五篇—接口发生异常如何统一处理
大家好!我是sum墨,一个一线的底层码农,平时喜欢研究和思考一些技术相关的问题并整理成文,限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。
807 0
《优化接口设计的思路》系列:第五篇—接口发生异常如何统一处理
|
机器学习/深度学习 人工智能 计算机视觉
【YOLOv8-Seg】实战三:LabVIEW+TensoRT实现YOLOv8-seg的极速推理(毫秒级)
【YOLOv8-Seg】实战三:LabVIEW+TensoRT实现YOLOv8-seg的极速推理(毫秒级)
639 0
【YOLOv8-Seg】实战三:LabVIEW+TensoRT实现YOLOv8-seg的极速推理(毫秒级)
|
消息中间件 Linux Docker
Centos7 安装 RabbitMQ
Centos7 安装 RabbitMQ
343 0