扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
在JDK 1.3以后的版本中,Java通过java.util.Timer和java.util.TimerTask这两个类提供了简单的任务调度的功能,我们称之为JDK Timer。
JDK Timer允许按照固定频率重复执行某项任务,这比直接通过编写底层线程程序进行任务调度要轻松许多,但是对于诸如“在每周一10:00执行任务”这种日历相关的任务调度需求来说,JDK Timer就难以应付了。
此外,JDK Timer只适合对执行时间非常短的任务进行调度,因为在Timer中所有TimerTask都在同一背景线程中执行,长时间的任务会严重影响到Timer的调度工作。
TimerTask代表一个需要多次执行的任务,它实现了Runnable接口,可以在run()方法中定义任务逻辑。而Timer负责制定调度规则并负责调度TimerTask。
TimerTask相当于Quartz中Job,代表一个被调度的任务。两者最主要区别在于:每当执行任务时,Quartz都会创建一个Job实例,而JDK Timer则使用相同的TimerTask实例。所以如果TimerTask类中拥有状态,则这些状态对于后面的执行是可见的,从这点上来说,TimerTask更象是StatefulJob而非Job。TimerTask实现了Runnable接口,是一个抽象类,它只有以下3个方法:
abstract void run():子类覆盖这个方法并定义任务运行的逻辑,每次执行任务时,run()方法被执行一次;
boolean cancel():取消任务。如果任务被安排运行一次且任务未执行时,任务将永远不会运行;如果任务被安排执行多次,调用该方法后,将取消后面的执行安排;
long scheduledExecutionTime():返回此任务最近实际执行的安排执行时间。如果在任务执行过程中调用此方法,则返回值此次执行对应的安排执行时间(一个任务的实现执行时间和安排的计划执行时间并不一致)。该方法一般在run()方法内调用,你可以通过该方法判断本次执行的时间点是否过晚,并据此决定是否要取消本次的运行。该方法一般在固定频率执行时使用才会有意义。
Timer只能以这样的方式对任务进行调度:在延迟一段时间或在指定时间点后运行一次任务或周期性的运行任务。实际上,Timer内部使用Object#wait(long time)进行任务的时间调度,这种机制不能保证任务的实时执行,只是一个粗略的近似值。
每一个Timer对象有一个对应的“背景线程”,它负责调度并执行Timer中所有的TimerTask。由于所有的TimerTask都在这个线程中执行,所以TimerTask的执行时间应该非常短,如果一个TimerTask的执行占用了过多的时间,后面的任务就会受到影响。由于后续任务在调度时间轴上受到了“挤压”,可能会造成“扎堆”执行的情况。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者