`

java定时器介绍与Spring中定时器的配置

 
阅读更多

###3.

原文链接:http://badwing.javaeye.com/blog/674263

文章分类:Java编程

好多朋友用过Windows的任务计划,也有不少程序迷自己曾写过时钟报警、系统自动关机等趣味程序,可却很少有朋友Web工程实现过类似功能。
当Web工程启动时,定时器能自动开始计时,整个Web工程的生命期里,定时器每晚深夜触发一次任务。因此定时器的存放位置也值得考查,不能简单的存于单个Servlet或JavaBean,必须能让定时器宿主的存活期为整个Web工程生命期,工程启动时能自动加载运行。结合这两点,跟 Servlet上下文有关的侦听器就最合适不过了,通过工程的配置文件加以合理配置,会工程启动时自动运行,并整个工程生命期处于监听状态。

下面就Servlet侦听器结合Java定时器来讲述整个实现过程。要运用Servlet侦听器需要实现 javax.servlet.ServletContextListener接口,同时实现它的contextInitialized (ServletContextEvent event)和contextDestroyed(ServletContextEvent event)两个接口函数。考虑定时器有个建立和销毁的过程,看了前面两个接口函数,就不容置疑的把建立的过程置入 contextInitialized,把销毁的过程置入contextDestroyed了。
我把ServletContextListener的实现类取名为ContextListener,其内添加一个定时器,示例代码如下所示:
import java.util.Timer;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;

public class ContextListener
extends HttpServlet
implements ServletContextListener {
public 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。示例代码如下所示:
import java.util.*;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.*;

public class MyTask extends TimerTask {
private static final int C_SCHEDULE_HOUR = 0;
private static boolean isRunning = false;
private ServletContext context = null;

public MyTask() {
}
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 添加自定义的详细任务,以下只是示例
//系统定时接收邮件
Email email=new Email();
email.recieve();

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

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

<listener>
<listener-class>com.test.ContextListener</listener-class>
</listener>

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

 

 

 

##!转自 http://batitan.iteye.com/blog/253483

 

定时任务:Java中Timer和TimerTask的使用

java.util.Timer定时器,实际上是个线程,定时调度所拥有的TimerTasks。
一个TimerTask实际上就是一个拥有run方法的类,需要定时执行的代码放到run方法体内,TimerTask一般是以匿名类的方式创建。

一个完整的Timer:
Java代码 复制代码 收藏代码
  1. java.util.Timer timer = new java.util.Timer(true);
  2. // true 说明这个timer以daemon方式运行(优先级低,
  3. // 程序结束timer也自动结束),注意,javax.swing
  4. // 包中也有一个Timer类,如果import中用到swing包,
  5. // 要注意名字的冲突。
  6. TimerTask task = new TimerTask() {
  7. publicvoid run() {
  8. ... //每次需要执行的代码放到这里面。
  9. }
  10. };
  11. //以下是几种调度task的方法:
  12. timer.schedule(task, time);
  13. // time为Date类型:在指定时间执行一次。
  14. timer.schedule(task, firstTime, period);
  15. // firstTime为Date类型,period为long
  16. // 从firstTime时刻开始,每隔period毫秒执行一次。
  17. timer.schedule(task, delay)
  18. // delay 为long类型:从现在起过delay毫秒执行一次
  19. timer.schedule(task, delay, period)
  20. // delay为long,period为long:从现在起过delay毫秒以后,每隔period
  21. // 毫秒执行一次。
java.util.Timer timer = new java.util.Timer(true); 
// true 说明这个timer以daemon方式运行(优先级低, 
// 程序结束timer也自动结束),注意,javax.swing 
// 包中也有一个Timer类,如果import中用到swing包, 
// 要注意名字的冲突。 

TimerTask task = new TimerTask() { 
public void run() { 
... //每次需要执行的代码放到这里面。 
} 
}; 

//以下是几种调度task的方法: 

timer.schedule(task, time); 
// time为Date类型:在指定时间执行一次。 

timer.schedule(task, firstTime, period); 
// firstTime为Date类型,period为long 
// 从firstTime时刻开始,每隔period毫秒执行一次。 

timer.schedule(task, delay) 
// delay 为long类型:从现在起过delay毫秒执行一次 

timer.schedule(task, delay, period) 
// delay为long,period为long:从现在起过delay毫秒以后,每隔period 
// 毫秒执行一次。




下面是一个完整的例子,由两个类组成,一个定制任务,一个调用java.util.Timer

定制任务:
Java代码 复制代码 收藏代码
  1. import java.util.Timer;
  2. publicclass TimerTaskTest extends java.util.TimerTask{
  3. @Override
  4. publicvoid run() {
  5. // TODO Auto-generated method stub
  6. System.out.println("start");
  7. }
  8. }
import java.util.Timer;

public class TimerTaskTest extends java.util.TimerTask{

@Override
public void run() {
   // TODO Auto-generated method stub
   System.out.println("start");
}
}

2.调用java.util.Timer
Java代码 复制代码 收藏代码
  1. import java.util.Timer;
  2. publicclass Test {
  3. publicstaticvoid main(String[] args){
  4. Timer timer = new Timer();
  5. timer.schedule(new TimerTaskTest(), 1000, 2000);
  6. }
  7. }
import java.util.Timer;

public class Test {
public static void main(String[] args){
   Timer timer = new Timer();
   timer.schedule(new TimerTaskTest(), 1000, 2000);
}
}


根据上面的介绍,便可以在1秒后,每隔2秒执行一次程序

###1转自:http://blog.csdn.net/notonlyforshe/article/details/7329091

 

  1. 1定时器的作用
  2. 在实际的开发中,如果项目中需要定时执行或者需要重复执行一定的工作,定时器显现的尤为重要。
  3. 当然如果我们不了解定时器就会用线程去实现,例如:
  4. package org.lzstone.action
  5. publicclass FinanceAction extends Thread{
  6. private Date date;
  7. publicvoid run{
  8. try{
  9. while(true){
  10. Thread.sleep((int)(Math.random()*1000));
  11. date = new Date();
  12. //定时执行任务
  13. }
  14. }catch(Exception e){
  15. e.printStackTrace();
  16. }
  17. }
  18. }
  19. 自己实现定时器的工作很复杂,如果实现不好占用内存过多,系统就此Over,所以处理定时执行或者重复执行的任务,定时器是很好的选择
  20. 2.java中常见的定时器
  21. 1)借助Java.util.Timer来实现
  22. 2)OpenSymphony社区提供的Quartz来实现
  23. 3.介绍Timer
  24. 利用Timer开发定时任务是主要分为两个步骤:
  25. 1)创建定时任务类
  26. 示例代码:
  27. package org.lzstone.action
  28. import java.util.TimeTask
  29. publicclass LzstoneTimeTask extends TimeTask{
  30. publicvoid run(){
  31. //执行的定时器任务
  32. }
  33. }
  34. 2)运行定时任务,运行定时任务分为两种方式:
  35. 2.1)程序直接启动
  36. 示例代码:
  37. package org.lzstone.action
  38. publicclass LzstoneMain{
  39. .......
  40. publicvoid run(){
  41. //执行定时器的任务
  42. //创建实例
  43. Timer timer = new Timer();
  44. 参数:
  45. new LzstoneTimeTask()- 所要安排的任务。
  46. 0- 执行任务前的延迟时间,单位是毫秒。
  47. 1*1000- 执行各后续任务之间的时间间隔,单位是毫秒。
  48. timer.schedule(new LzstoneTimeTask(),0,1*1000);
  49. }
  50. }
  51. 2.2)web监听方式
  52. 示例代码:
  53. package org.lzstone.action
  54. publicclass LzstoneMain implements ServletContextListener{
  55. private Timer timer = null;
  56. //初始化监听器,创建实例,执行任务
  57. publicvoid contextInitialized(ServletContextEvent event){
  58. timer = new Timer();
  59. timer.schedule(new LzstoneTimeTask(),0,1*1000);
  60. }
  61. //销毁监听器,停止执行任务
  62. publicvoid contextDestroyed(ServletContextEvent event){
  63. //注意,在此计时器调用的计时器任务的 run 方法内调用此方法,就可以绝对确保正在执行的任务是此计时器所执行的最后一个任务。
  64. timer.cancel();
  65. }
  66. }
  67. web.xml配置
  68. <listener>
  69. <listener-class>
  70. org.lzstone.action.LzstoneMain
  71. </listener-class>
  72. </listener>
  73. 4. 介绍Quartz
  74. Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,可以用来创建简单或者复杂的定时任务,利用Quartz开发定时任务的步骤与Timer类
  75. 似。
  76. 利用Quartz开发定时任务是主要分为两个步骤:
  77. 1)创建定时任务类
  78. 示例代码:
  79. package org.lzstone.action
  80. publicclass LzstoneTimeTask implements Job{
  81. publicvoid execute(JobExecutionContext context) throws JobExecutionException{
  82. //执行的定时器任务
  83. }
  84. }
  85. 2)运行定时任务,运行定时任务分为两种方式:
  86. 2.1)程序直接启动,创建任务调度器及配置相应的任务计划
  87. 示例代码:
  88. package org.lzstone.action
  89. publicclass LzstoneMain{
  90. privatestatic Scheduler sched;
  91. publicstaticvoid run() throws Exception{
  92. //创建LzstoneTimeTask的定时任务
  93. JobDetail jobDetail = new JobDetail("lzstoneJob",sched.DEFAULT_GROUP,LzstoneTimeTask.class);
  94. //目标 创建任务计划
  95. CronTrigger trigger = new CronTrigger("lzstoneTrigger","lzstone","0 0 12 * * ?");
  96. //0 0 12 * * ? 代表每天的中午12点触发
  97. sched = new org.quartz.impl.StdSchedulerFactory().getScheduler();
  98. sched.scheduleJob(jobDetail,trigger);
  99. sched.start();
  100. }
  101. //停止
  102. publicstaticvoid stop() throws Exception{
  103. sched.shutdown();
  104. }
  105. }
  106. //执行
  107. publicclass Main{
  108. .............
  109. publicvoid run(){
  110. LzstoneMain.run();
  111. }
  112. ............
  113. }
  114. 2.2)web监听方式
  115. 示例代码:
  116. package org.lzstone.action
  117. publicclass LzstoneMainListener implements ServletContextListener{
  118. private Timer timer = null;
  119. //初始化监听器,创建实例,执行任务
  120. publicvoid contextInitialized(ServletContextEvent event){
  121. LzstoneMain.run();
  122. }
  123. //销毁监听器,停止执行任务
  124. publicvoid contextDestroyed(ServletContextEvent event){
  125. LzstoneMain.stop();
  126. }
  127. }
  128. web.xml配置
  129. <listener>
  130. <listener-class>
  131. org.lzstone.action.LzstoneMainListener
  132. </listener-class>
  133. </listener>
  134. 5.对比
  135. Timer方式实现定时器,原理简单,实现方便,在执行简单的任务比较方便,不足之处是无法确定执行时间,并且依赖性比较强,必须继承指定的类
  136. Quartz方式实现定时器,方便,清晰指定启动时间,定时参数比较灵活,容易实现比较复杂的定时任务,不足之处是需要实现特定接口,加载其框架
  137. 两种方式各有优缺点,在特定场合可以根据其特点选择使用。
  138. 6.Spring定时任务
  139. Spring定时任务对Timer与Quartz都提供了支持,并且实现步骤基本一样
  140. 首先配置Spring对Timer的支持
  141. 1.1 创建定时任务类
  142. package org.lzstone.action
  143. import java.util.TimeTask
  144. publicclass LzstoneTimeTask extends TimeTask{
  145. publicvoid run(){
  146. //执行的定时器任务
  147. }
  148. }
  149. 1.2 注册定时任务类,配置任务计划与任务调度器
  150. 在项目的WEB-INF下面创建TimerConfig.xml文件
  151. <?xml version="1.0" encoding="UTF-8"?>
  152. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN""http://www.springframework.org/dtd/spring-beans.dtd">
  153. <beans>
  154. <bean>
  155. <!--注册定时执行任务实体-->
  156. <bean id="lzstoneTimeTask"class="org.lzstone.action.LzstoneTimeTask"/>
  157. <!--注册定时器信息-->
  158. <bean id="taskInfo"class="org.springframework.scheduling.timer.ScheduledTimerTask">
  159. <!--第一次执行任务前需要等待的时间,这里设置为3秒-->
  160. <property name="delay">
  161. <value>3000</value>
  162. </property>
  163. <!--设置任务的执行周期 这里设置为4秒-->
  164. <property name="period">
  165. <value>4000</value>
  166. </property>
  167. <!--设置具体执行的任务 这里设置为lzstoneTimeTask-->
  168. <property name="timerTask">
  169. <ref local="lzstoneTimeTask"/>
  170. </property>
  171. </bean>
  172. <!--配置定时器任务的调度器-->
  173. <bean id="timerFactory"class="org.springframework.scheduling.timer.TimerFactoryBean">
  174. <!--注册定时器列表-->
  175. <property name="scheduledTimerTasks">
  176. <list>
  177. <ref local="taskInfo"/>
  178. ........
  179. </list>
  180. </property>
  181. </bean>
  182. </beans>
  183. 1.3 web项目中的启动设置
  184. <context-param>
  185. <param-name>contextConfigLocation</param-name>
  186. <param-value>/WEB-INF/TimerConfig.xml</param-value>
  187. </context-param>
  188. <listener>
  189. <listener-class>
  190. org.springframework.web.context.ContextLoaderListener
  191. </listener-class>
  192. </listener>
  193. 配置Spring对Quartz的支持
  194. 2.1 创建定时任务类
  195. package org.lzstone.action
  196. publicclass LzstoneQuartzTask{
  197. publicvoid execute(){
  198. //执行的定时器任务
  199. }
  200. }
  201. 2.2 注册定时任务类,配置任务计划与任务调度器
  202. 在项目的WEB-INF下面创建QuartzConfig.xml文件
  203. <?xml version="1.0" encoding="UTF-8"?>
  204. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN""http://www.springframework.org/dtd/spring-beans.dtd">
  205. <beans>
  206. <bean>
  207. <!--注册定时执行任务实体-->
  208. <bean id="lzstoneQuartzTask"class="org.lzstone.action.LzstoneQuartzTask"/>
  209. <!--注册定时器信息-->
  210. <bean id="taskInfo"class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
  211. <!--指定要执行的定时任务类 这里是LzstoneQuartzTask-->
  212. <property name="targetObject">
  213. <ref local="lzstoneQuartzTask"/>
  214. </property>
  215. <!--指定定时器任务类要执行的方法名称 这里是execute-->
  216. <property name="targetMethod">
  217. <value>execute</value>
  218. </property>
  219. </bean>
  220. <!--配置定时器任务的调度器-->
  221. <bean id="quartzTrigger"class="org.springframework.scheduling.quartz.CronTriggerBean">
  222. <!--声明要运行的实体-->
  223. <property name="jobDetail">
  224. <ref local="taskInfo"/>
  225. </property>
  226. <!--设置运行时间-->
  227. <property name="cronExpression">
  228. <value>0012 * * ?</value>
  229. </property>
  230. </bean>
  231. <!--注册监听器-->
  232. <bean id="registerQuartz"class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
  233. <!--注册定时器实体 集合-->
  234. <property name="triggers">
  235. <list>
  236. <ref local="quartzTrigger"/>
  237. </list>
  238. </property>
  239. </bean>
  240. </beans>
  241. 2.3 web项目中的启动设置
  242. <context-param>
  243. <param-name>contextConfigLocation</param-name>
  244. <param-value>/WEB-INF/QuartzConfig.xml</param-value>
  245. </context-param>
  246. <listener>
  247. <listener-class>
  248. org.springframework.web.context.ContextLoaderListener
  249. </listener-class>
  250. </listener>
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics