如何在Web工程中实现任务计划调度--Tomcat定时器实现

25 篇文章 0 订阅
经过查阅较多相关资料,发现Java定时器(java.util.Timer)有定时触发计划任务的功能,通过配置定时器的间隔时间,在某一间隔时间段之后会自动有规律的调用预先所安排的计划任务(java.util.TimerTask)。另外,由于我们希望当Web工程启动时,定时器能自动开始计时,在整个Web工程的生命期里,定时器能在每晚深夜触发一次报表计算引擎。因此定时器的存放位置也值得考查,不能简单的存在于单个Servlet或JavaBean中,必须能让定时器宿主的存活期为整个Web工程生命期,在工程启动时能自动加载运行。结合这两点,跟Servlet上下文有关的侦听器就最合适不过了,通过在工程的配置文件中加以合理配置,会在工程启动时自动运行,并在整个工程生命期中处于监听状态。

......下面就Servlet侦听器结合Java定时器来讲述整个实现过程。要运用Servlet侦听器需要实现javax.servlet.ServletContextListener接口,同时实现它的contextInitialized(ServletContextEvent    event)和contextDestroyed(ServletContextEvent    event)两个接口函数。考虑定时器有个建立和销毁的过程,看了前面两个接口函数,就不容置疑的把建立的过程置入contextInitialized,把销毁的过程置入contextDestroyed了。

<script type="text/javascript"> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>

......我把ServletContextListener的实现类取名为ContextListener,在其内添加一个定时器,示例代码如下所示(为考虑篇幅,仅提供部分代码供读者参考):

程序代码:  

程序代码:
private java.util.Timer timer = null;
public void contextInitialized(ServletContextEvent event) {
timer = new java.util.Timer(true);
event.getServletContext().log("定时器已启动"); 
timer.schedule(new MyTask(event.getServletContext()), 0, 60*60*1000);
event.getServletContext().log("已经添加任务调度表");
}
public void contextDestroyed(ServletContextEvent event) {
timer.cancel();
event.getServletContext().log("定时器销毁");
}  


......以上代码中,    timer.schedule(new    MyTask(event.getServletContext()),    0,    60*60*1000)这一行为定时器调度语句,其中MyTask是自定义需要被调度的执行任务(在我的财政数据中心项目中就是报表计算引擎入口),从java.util.TimerTask继承,下面会重点讲述,第三个参数表示每小时(即60*60*1000毫秒)被触发一次,中间参数0表示无延迟。其它代码相当简单,不再详细说明。

......下面介绍MyTask的实现,上面的代码中看到了在构造MyTask时,传入了javax.servlet.ServletContext类型参数,是为记录Servlet日志方便而传入,因此需要重载MyTask的构造函数(其父类java.util.TimerTask原构造函数是没有参数的)。在timer.schedule()的调度中,设置了每小时调度一次,因此如果想实现调度任务每24小时被执行一次,还需要判断一下时钟点,以常量C_SCHEDULE_HOUR表示(晚上12点,也即0点)。同时为防止24小时执行下来,任务还未执行完(当然,一般任务是没有这么长的),避免第二次又被调度以引起执行冲突,设置了当前是否正在执行的状态标志isRunning。示例代码如下所示:
程序代码:
 
程序代码:
private static final int C_SCHEDULE_HOUR = 0;
private static boolean isRunning = false;
private ServletContext context = null;
public MyTask(ServletContext context) {
this.context = context;
}
public void run() {
Calendar cal = Calendar.getInstance(); 
if (!isRunning) { 
if (C_SCHEDULE_HOUR == cal.get(Calendar.HOUR_OF_DAY)) { 
isRunning = true
context.log("开始执行指定任务");

//TODO 添加自定义的详细任务,以下只是示例
int i = 0;
while (i++ < 10) {
context.log("已完成任务的" + i + "/" + 10);

isRunning = false;
context.log("指定任务执行结束"); 

else {
context.log("上一次任务执行还未结束");
}
}  


......上面代码中"//TODO……"之下四行是真正被调度执行的演示代码(在我的财政数据中心项目中就是报表计算过程),您可以换成自己希望执行的语句。

......到这儿,ServletContextListener和MyTask的代码都已完整了。最后一步就是把ServletContextListener部署到您的Web工程中去,在您工程的web.xml配置文件中加入如下三行:
程序代码:  

程序代码:
<listener>
<listener-class>com.test.ContextListener</listener-class>
</listener>  


......当然,上面的com.test得换成您自己的包名了。保存web.xml文件后,把工程打包部署到Tomcat中即可。任务会在每晚12点至凌晨1点之间被执行,上面的代码会在Tomcat的日志文件中记录如下:

2003-12-05    0:21:39    开始执行指定任务
2003-12-05    0:21:39    已完成任务的1/10
……
2003-12-05    0:21:39    已完成任务的10/10
2003-12-05    0:21:39    指定任务执行结束

......以上代码在Tomcat    4.1.29以及Tomcat    5.0.16上调试通过。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个基本的士兰微定时器实现任务调度的代码示例: ```c #include "stm32f10x.h" // 定义任务结构体,包括任务函数和任务执行周期 typedef struct { void (*task_func)(void); uint32_t period; } task_t; // 定义任务数组,包括三个任务 task_t tasks[] = { {task1, 1000}, // 每1000ms执行一次task1函数 {task2, 2000}, // 每2000ms执行一次task2函数 {task3, 5000}, // 每5000ms执行一次task3函数 }; // 定义计数器,用于计算定时器断的次数 volatile uint32_t counter = 0; // 定时器断处理函数 void TIM2_IRQHandler(void) { if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { // 清除断标志位 TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // 计数器加1 counter++; } } // 初始化定时器 void TIM2_Init(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; // 使能定时器时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 初始化定时器结构体 TIM_TimeBaseInitStruct.TIM_Prescaler = 7200 - 1; // 分频系数,得到1ms的时间基准 TIM_TimeBaseInitStruct.TIM_Period = 1000 - 1; // 定时器周期为1s TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct); // 使能定时器断 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); // 启动定时器 TIM_Cmd(TIM2, ENABLE); } int main(void) { // 初始化定时器 TIM2_Init(); while (1) { // 检查任务是否需要执行 for (int i = 0; i < sizeof(tasks) / sizeof(task_t); i++) { if (counter % tasks[i].period == 0) { tasks[i].task_func(); } } } } // 任务函数1 void task1(void) { // 执行任务1的代码 } // 任务函数2 void task2(void) { // 执行任务2的代码 } // 任务函数3 void task3(void) { // 执行任务3的代码 } ``` 在上述代码,我们使用定时器 TIM2 来实现任务调度。我们定义了一个任务结构体 task_t,包含了任务函数和任务执行周期。我们定义了三个任务,分别是 task1、task2、task3,它们的执行周期分别为 1000ms、2000ms、5000ms。 在主函数,我们进入一个死循环,在循环检查每个任务是否需要执行。如果计数器 counter 能够整除任务的执行周期,就执行对应的任务函数。 在定时器断处理函数,我们每次触发定时器断,就将计数器 counter 加1。这样就能够按照设定的周期执行任务函数了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值