首页IT科技java的定时器能不能提供实时保证 可能提前也可能推迟(Java Timer(定时器))

java的定时器能不能提供实时保证 可能提前也可能推迟(Java Timer(定时器))

时间2025-04-30 06:00:22分类IT科技浏览3965
导读:概述: Timer是一种定时器工具,用来在一个后台线程计划执行指定任务。它可以安排任务“执行一次”或者定期“执行多次”。 然而在实际的开发过程当中,经常需要一些周期性的操作,比如每5分钟执行某一操作等。 对于这样的操作最方便、高效的实现方式...

概述:

Timer是一种定时器工具           ,用来在一个后台线程计划执行指定任务            。它可以安排任务“执行一次           ”或者定期“执行多次                ”                 。 然而在实际的开发过程当中                ,经常需要一些周期性的操作      ,比如每5分钟执行某一操作等    。 对于这样的操作最方便           、高效的实现方式就是使用java.util.Timer工具类         。

方法摘要:

schedule(TimerTask task, Date time) // 安排在 "指定的时间" 执行 指定的任务                  。(只执行一次) schedule(TimerTask task,long delay) // 安排在指定延迟后执行指定的任务 schedule(TimerTask task, Date firstTime , long period) // 安排指定的任务在 "指定的时间 " 开始进行 "重复" 的固定延迟执行 schedule(TimerTask task,long delay,long period)// 安排指定的任务指定的延迟后开始进行重复的固定延迟执行. scheduleAtFixedRate(TimerTask task,Date firstTime,long period)// 安排指定的任务在指定的时间开始进行重复的固定速率执行. scheduleAtFixedRate(TimerTask task,long delay,long period)//安排指定的任务在指定的延迟后开始进行重复的固定速率执行. Timer.cancal()// 终止此计时器         ,丢弃所有当前已安排的任务       。 Timer.purge()// 从此计时器的任务队列中移除所有已取消的任务      。 TimerTask.cancal()// 把当前任务取消

固定延迟:意味着执行将在最后一次执行开始后的一段时间内开始                ,即使它被延迟(因此它本身被延迟)                  。也就是说任务的 下一次执行时间 是相对于 上一次实际执行完成的时间点          ,因此执行时间会不断延后

固定频率:意味着每次执行都将遵守初始计划      ,无论之前的执行是否被延迟          。也就是说任务的 下一次执行时间 是相对于 上一次开始执行的时间点                ,因此执行时间不会延后

关于这两种调度方式            ,让我们看看如何使用它们:

为了使用固定延迟调度   ,schedule()方法还有两个重载                ,每个重载都使用一个额外的参数来表示以毫秒为单位的周期性   。为什么两次重载?因为仍然有可能在某个时刻或某个延迟之后开始执行任务                  。

至于固定频率调度               ,我们有两个scheduleAtFixedRate()方法,它们的周期也是以毫秒为单位的             。同样             ,我们有一种方法可以在给定的日期和时间启动任务                 ,还有一种方法可以在给定的延迟后启动任务。

注意一点:如果一个任务的执行时间超过了执行周期   ,那么无论我们使用固定延迟还是固定速率           ,它都会延迟整个执行链               。(固定速率会连续执行                ,固定延迟会等待延迟再执行)

具体代码

schedule(TimerTask task, Date time)

/** * @PROJECT_NAME: demo * @DESCRIPTION: 指定时间执行 */ public class TimerDemo { public static void main(String[] args) { Calendar ca = Calendar.getInstance(); System.out.println(ca.getTime()); ca.set(Calendar.SECOND, ca.get(Calendar.SECOND) + 5); new Timer().schedule(new TimerTask() { @Override public void run() { System.out.println(new Date(scheduledExecutionTime()); } }, ca.getTime()); } }

schedule(TimerTask task,long delay)

/** * @PROJECT_NAME: demo * @DESCRIPTION: 延迟指定时间后执行 */ public class DelayDemo { public static void main(String[] args) { System.out.println(new Date()); new Timer().schedule(new TimerTask() { @Override public void run() { System.out.println(new Date(scheduledExecutionTime()); } }, 2000); } }

schedule(TimerTask task, Date firstTime, long period)

/** * @PROJECT_NAME: demo * @DESCRIPTION: 安排指定的任务在 "指定的时间 " 开始进行 "重复" 的固定延迟执行 */ public class FirstAndPeriodDemo { public static void main(String[] args) { Calendar ca = Calendar.getInstance(); System.out.println(ca.getTime()); ca.set(Calendar.SECOND, ca.get(Calendar.SECOND) + 2); new Timer().schedule(new TimerTask() { @Override public void run() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(new Date(scheduledExecutionTime())); } }, ca.getTime(),2000); } }

第一次任务延迟了2s      ,然后之后因为实现线程执行时间为3s         ,所以在任务结束时在开始下一次任务                。

schedule(TimerTask task,long delay,long period)

/** * @PROJECT_NAME: demo * @DESCRIPTION: 安排指定的任务在“指定的延迟      ”后开始进行“重复         ”的固定延迟执行 */ public class DelayAndPeriodDemo { public static void main(String[] args) { System.out.println(new Date()); new Timer().schedule(new TimerTask() { @Override public void run() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(new Date(scheduledExecutionTime())); } }, 1000,2000); } }

scheduleAtFixedRate(TimerTask task,Date firstTime,long period)

/** * @PROJECT_NAME: demo * @DESCRIPTION: */ public class FixAndFirstDemo { public static void main(String[] args) { System.out.println(new Date()); new Timer().scheduleAtFixedRate(new TimerTask() { @Override public void run() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(new Date(scheduledExecutionTime())); } }, 1000, 2000); } }

按照固定速率执行  。

但是                ,这儿引出了另外一个问题            。既然 Timer 内部是单线程实现的         ,在执行间隔为2秒                、任务实际执行为3秒的情况下      , scheduleAtFixedRate 是如何做到2秒输出一次的呢?

【特别注意】

这儿其实是一个障眼法                 。需要重点关注的是                ,打印方法输出的值是通过调用 scheduledExecutionTime() 来生成的            ,而这个方法并不一定是任务真实执行的时间   ,而是当前任务应该执行的时间    。

源码理解

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
上网本设置u盘启动(在上网本中,如何用U盘重新安装系统?) 热血江湖手游私sf平台版下载2024(热血江湖私服病毒)