Timer 和 ScheduledExecutor 都仅能提供基于开始时间与重复间隔的任务调度,不能胜任更加复杂的调度需求。比如,设置每星期二的 16:38:10 执行任务。该功能使用 Timer 和 ScheduledExecutor 都不能直接实现,但我们可以借助 Calendar 间接实现该功能。
清单 3. 使用 ScheduledExcetuor 和 Calendar 进行任务调度
package com.ibm.scheduler; import java.util.Calendar; import java.util.Date; import java.util.TimerTask; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class ScheduledExceutorTest2 extends TimerTask { private String jobName = ""; public ScheduledExceutorTest2(String jobName) { super(); this.jobName = jobName; } @Override public void run() { System.out.println("Date = "+new Date()+", execute " + jobName); } /** * 计算从当前时间currentDate开始,满足条件dayOfWeek, hourOfDay, * minuteOfHour, secondOfMinite的最近时间 * @return */ public Calendar getEarliestDate(Calendar currentDate, int dayOfWeek, int hourOfDay, int minuteOfHour, int secondOfMinite) { //计算当前时间的WEEK_OF_YEAR,DAY_OF_WEEK, HOUR_OF_DAY, MINUTE,SECOND等各个字段值 int currentWeekOfYear = currentDate.get(Calendar.WEEK_OF_YEAR); int currentDayOfWeek = currentDate.get(Calendar.DAY_OF_WEEK); int currentHour = currentDate.get(Calendar.HOUR_OF_DAY); int currentMinute = currentDate.get(Calendar.MINUTE); int currentSecond = currentDate.get(Calendar.SECOND); //如果输入条件中的dayOfWeek小于当前日期的dayOfWeek,则WEEK_OF_YEAR需要推迟一周 boolean weekLater = false; if (dayOfWeek < currentDayOfWeek) { weekLater = true; } else if (dayOfWeek == currentDayOfWeek) { //当输入条件与当前日期的dayOfWeek相等时,如果输入条件中的 //hourOfDay小于当前日期的 //currentHour,则WEEK_OF_YEAR需要推迟一周 if (hourOfDay < currentHour) { weekLater = true; } else if (hourOfDay == currentHour) { //当输入条件与当前日期的dayOfWeek, hourOfDay相等时, //如果输入条件中的minuteOfHour小于当前日期的 //currentMinute,则WEEK_OF_YEAR需要推迟一周 if (minuteOfHour < currentMinute) { weekLater = true; } else if (minuteOfHour == currentSecond) { //当输入条件与当前日期的dayOfWeek, hourOfDay, //minuteOfHour相等时,如果输入条件中的 //secondOfMinite小于当前日期的currentSecond, //则WEEK_OF_YEAR需要推迟一周 if (secondOfMinite < currentSecond) { weekLater = true; } } } } if (weekLater) { //设置当前日期中的WEEK_OF_YEAR为当前周推迟一周 currentDate.set(Calendar.WEEK_OF_YEAR, currentWeekOfYear + 1); } // 设置当前日期中的DAY_OF_WEEK,HOUR_OF_DAY,MINUTE,SECOND为输入条件中的值。 currentDate.set(Calendar.DAY_OF_WEEK, dayOfWeek); currentDate.set(Calendar.HOUR_OF_DAY, hourOfDay); currentDate.set(Calendar.MINUTE, minuteOfHour); currentDate.set(Calendar.SECOND, secondOfMinite); return currentDate; } public static void main(String[] args) throws Exception { ScheduledExceutorTest2 test = new ScheduledExceutorTest2("job1"); //获取当前时间 Calendar currentDate = Calendar.getInstance(); long currentDateLong = currentDate.getTime().getTime(); System.out.println("Current Date = " + currentDate.getTime().toString()); //计算满足条件的最近一次执行时间 Calendar earliestDate = test .getEarliestDate(currentDate, 3, 16, 38, 10); long earliestDateLong = earliestDate.getTime().getTime(); System.out.println("Earliest Date = " + earliestDate.getTime().toString()); //计算从当前时间到最近一次执行时间的时间间隔 long delay = earliestDateLong - currentDateLong; //计算执行周期为一星期 long period = 7 * 24 * 60 * 60 * 1000; ScheduledExecutorService service = Executors.newScheduledThreadPool(10); //从现在开始delay毫秒之后,每隔一星期执行一次job1 service.scheduleAtFixedRate(test, delay, period, TimeUnit.MILLISECONDS); } } Output: Current Date = Wed Feb 02 17:32:01 CST 2011 Earliest Date = Tue Feb 8 16:38:10 CST 2011 Date = Tue Feb 8 16:38:10 CST 2011, execute job1 Date = Tue Feb 15 16:38:10 CST 2011, execute job1
实现了每星期二 16:38:10 调度任务的功能。其核心在于根据当前时间推算出最近一个星期二 16:38:10 的绝对时间,然后计算与当前时间的时间差,作为调用 ScheduledExceutor 函数的参数。计算最近时间要用到 java.util.calendar 的功能。首先需要解释 calendar 的一些设计思想。Calendar 有以下几种唯一标识一个日期的组合方式:
YEAR + MONTH + DAY_OF_MONTH YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK YEAR + DAY_OF_YEAR YEAR + DAY_OF_WEEK + WEEK_OF_YEAR |
上述组合分别加上 HOUR_OF_DAY + MINUTE + SECOND 即为一个完整的时间标识。本例采用了最后一种组合方式。输入为 DAY_OF_WEEK, HOUR_OF_DAY, MINUTE, SECOND 以及当前日期 , 输出为一个满足 DAY_OF_WEEK, HOUR_OF_DAY, MINUTE, SECOND 并且距离当前日期最近的未来日期。计算的原则是从输入的 DAY_OF_WEEK 开始比较,如果小于当前日期的 DAY_OF_WEEK,则需要向 WEEK_OF_YEAR 进一, 即将当前日期中的 WEEK_OF_YEAR 加一并覆盖旧值;如果等于当前的 DAY_OF_WEEK, 则继续比较 HOUR_OF_DAY;如果大于当前的 DAY_OF_WEEK,则直接调用 java.util.calenda 的 calendar.set(field, value) 函数将当前日期的 DAY_OF_WEEK, HOUR_OF_DAY, MINUTE, SECOND 赋值为输入值,依次类推,直到比较至 SECOND。读者可以根据输入需求选择不同的组合方式来计算最近执行时间。
相关推荐
本文由浅入深介绍四种任务调度的Java实现:ScheduledExecutor开源工具包Quartz开源工具包JCronTab此外,为结合实现复杂的任务调度,本文还将介绍Calendar的一些使用方法。Timer相信大家都已经非常熟悉java.util....
另外,合理的组件抽象设计使得开发一个组件非常简单,后续会提供更多组件,提供丰富的定时器(simple、calendar、daily、cron),强大的任务管理(编辑、暂停、恢复调度、立即运行、复制任务、删除等等),支持联动...
net用Calendar实现blog日历
Java 之 Date 和 Calendar 实例
调度算法此算法运用了二层循环 和 借 用 时 隙 的 两 个 思 想 调度算法不仅在调度低时延和 低抖动的多类别实时数据流帧方面要优于 调 度 算 法而 且 在 一 定 程 度 上 也 保 证 了 各 优 先 级 队 列 调 度上的公
一个基于纯js实现的功能强大的JS Calendar (version 2.1)源码及例子
js基于calendar实现的橙色日期选择器源码.zip
主要是演示介绍了CalendarView日历控件的使用虽然日历控件在Web开发中有很多的解决方案,而且容易实现,但是在Android平台上的解决方案较少,源码目录中与大家分享了几款实现Calendar的示例,并附有实现这几款控件的...
layui 和 tui.calendar 资源, 内含layui日历联动tui.calendar日程表(日、周、月)实例 相关文档: https://nhn.github.io/tui.calendar/latest/Calendar#setCalendars ...
在网上找了几个calendar时间控件不太好用,于是修改了下,跟大家分享下。这个控件:1.可以只显示日期不显示时间; 2.也可以日期时间一起显示。
uni-app 插件 Calendar 日历多选 (不是范围选择)
可折叠的日历控件Calendar;
Calendar 实现日程显示,Jquery+ajax提示日程信息,附带json读取数据,循环输出表格,html页面实现。
内容概要:通过带着读者手写基于微信小程序calendar基础组件,没写很复杂的场景,场景是由选择隔日达,每日达,节假日达,非节假日达,自定义等场景而封装的,读者可以利用此组件进行需求的添加。此组件主要实现的...
Calendar, 在iOS上,显示和调度事件的一组视图和控制器 CalendarLib CalendarLib是一组视图和控制器,用于显示和调度iOS上的事件。警告:因为有些人可能已经注意到,这个项目最近没有更新,而且大量的问题/请求请求...
该项目为mattlewis92 / angular-calendar提供了一个调度程序视图组件。 入门 安装 NPM npm install angular-calendar-scheduler date-fns --save 纱 yarn add angular-calendar-scheduler date-fns 包含组件 ...
参考bootstrap datetimepicker和amazeui datepicker实现,可用于日历展示和日期选择。
java中时间类Date和Calendar的使用 java中时间类Date和Calendar的使用 <PRE class=java name="code">package cn.com; import java.text.DateFormat; import java.text.ParseException; import java.text....
<script type=\"text/javascript\" src=\"<%=ctx%>/js/calendar/calendar.js\"> <script type=\"text/javascript\" src=\"<%=ctx%>/js/calendar/calendar-zh.js\"> ...