Java Web定时器使用(转载).doc_第1页
Java Web定时器使用(转载).doc_第2页
Java Web定时器使用(转载).doc_第3页
Java Web定时器使用(转载).doc_第4页
Java Web定时器使用(转载).doc_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

这个类最终功能是每天某个时间点(如每晚22点)执行某一功能.首先介绍java定时器(java.util.Timer)有定时执行计划任务的功能,通过设定定时器的间隔时间,会自动在此间隔时间后执行预先安排好的任务(java.util. TimerTask)如: 每隔一个小时执行任务 timer.schedule(TimerTask, 0, 60 * 60 * 1000); schedule方法的第一个参数是需要执行的任务,此类的类型为java.util.TimerTask,第二个参数为执行任务前等待时间,此处0表示不等待,第三个参数为间隔时间,单位为毫秒由于我们希望当Web工程启动时,定时器能自动开始计时,这样在整个Web工程的生命期里,就会定时的执行任务,因此启动定时器的类不能是一般的类,此处用Servlet的监听器类来启动定时器,通过在配置文件里配置此监听器, 让其在工程启动时自动加载运行,存活期为整个Web工程生命期.要运用Servlet侦听器需要实现javax.servlet.ServletContextListener接口,以下是类设计:public class TimerListener implements ServletContextListener private Timer timer = null; private SampleTask sampleTask;Overridepublic void contextDestroyed(ServletContextEvent event) timer.cancel(); event.getServletContext().log(定时器销毁);Overridepublic void contextInitialized(ServletContextEvent event) timer = new Timer(true); sampleTask = new SampleTask(event.getServletContext(); event.getServletContext().log(定时器已启动); timer.schedule(sampleTask, 0, 60 * 60 * 1000); event.getServletContext().log (已经添加任务调度表);public class SampleTask extends TimerTask private ServletContext context; private static boolean isRunning = false; private static boolean flag = true; private static final int C_SCHEDULE_HOUR = 15; public SampleTask(ServletContext context) this.context = context; Overridepublic void run() Calendar cal = Calendar.getInstance(); if (!isRunning) if (C_SCHEDULE_HOUR = cal.get(Calendar.HOUR_OF_DAY) & flag) isRunning = true; context.log(开始执行指定任务); /需要执行的代码 isRunning = false; flag = false; context.log(指定任务执行结束); else context.log(上一次任务执行还未结束); if(C_SCHEDULE_HOUR != cal.get(Calendar.HOUR_OF_DAY) flag = true; 要使用此监听器需要在web.xml中配置,如下:包路径.TimerListener这样在web工程启动时,就会自动启动此监听器.JAVA中Timer定时器调度方法java timer中的时间调度方法主要有:schedule(TimerTask task, Date firstTime, long period) Schedules the specified task for repeated fixed-delay execution, beginning at the specified time.但是如果此时的firstTime小于(时间落后于)当前时间,那么task会立即执行,在调试的时候不方便,因为程序一启动就开始执行了,或许还没有到任务的触发点。schedule(TimerTask task, long delay, long period) Schedules the specified task for repeated fixed-delay execution, beginning after the specified delay.如果采用设置delay时间的方法,则可以进行处理。比如:设置执行时间为每天的13:50,如果启动的时候时间已经过了13:35,那么应该在明天的13:35进行执行。此时可以这样处理:Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR_OF_DAY, 13); cal.set(Calendar.MINUTE, 35); /cal.add(Calendar.DAY_OF_MONTH, 1); Date date = new Date(); date = cal.getTime(); Date now = new Date(); long interval = date.getTime() - now.getTime(); /should exec in next day if (interval 0) cal.add(Calendar.DAY_OF_MONTH, 1); date = cal.getTime(); interval = date.getTime() - now.getTime(); System.out.println(the interval time is: + interval); /the exec time interval is 2 secs. timer.schedule(echoTask, interval, 2 * 1000);如果delay的时间为负数,会报异常,因此,Calendar添加一天。JAVA WEB程序中添加定时器/这是我的定时器类,用来定时执行某段任务; package com.my.time;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;public class BugXmlTimer public Timer timer;public void timerStart()timer = new Timer();Date datetime=new Date();Date midnightDate=new Date();SimpleDateFormat sdf1 = new SimpleDateFormat(yyyy-MM-dd);SimpleDateFormat sdf2 = new SimpleDateFormat(yyyy-MM-dd HH:mm:ss);try midnightDate = sdf2.parse(sdf1.format(datetime)+ 23:00:00); catch (ParseException e) / TODO Auto-generated catch blocke.printStackTrace();long in=midnightDate.getTime()-datetime.getTime();System.out.println(before task);/立刻执行,然后每隔30s执行一次timer.schedule(new BugXmlTimerTask(), 0,30000);public void timerStop()if(timer!=null)timer.cancel();public static void main(String args)BugXmlTimer myTimer=new BugXmlTimer();/ TODO Auto-generated method stubmyTimer.timerStart();/这是执行任务的类,即每隔一段时间要做的事情在这里package com.my.time;import java.util.TimerTask;public class BugXmlTimerTask extends TimerTask Overridepublic void run() System.out.print(run task);/以下是出发定时操作的类,该类实现了ServletContextListenerpublic class MyTimerListener implements ServletContextListener private BugXmlTimer mytimer = new BugXmlTimer ();public void contextInitialized(ServletContextEvent event) mytimer.timerStart();public void contextDestroyed(ServletContextEvent event) mytimer.timerStop();然后在web.xml里部署一下,即可在程序启动后运行定时器了!com.my.time.MyTimerListener Java 定时器退出解决方案项目中用到了 Timer 每隔一段时间进行一些操作,现在发现有时候莫名其妙地挂在这个计时器上的操作都不做了,用“JConsole”查看其中的线程以后,发现这个定时器线程也不在了(定时器创建的时候带了名字 Timer timer = new Timer(MyTimer),所以直接能看到),由于日志太多,之前的日志已经找不到了,所以没有办法看是否是有异常发生以及发生在哪里。初步估计,是不是由于 TimerTask 中有异常抛出,如果定时器中没有处理的话,可能就会出问题。所以看了一下 java.util.Timer 的代码:1. / 在 TimerThread 中执行任务2. Timer.java:101:TimerThread3. / TimerThread 的入口4. / 这里只有一个 try/finally,如果 mainloop 中有异常抛出的话,肯定就结束运行。5. Timer.java:503:TimerThread.run()6. / 主循环体,其中只抓住了 InterruptedException 异常,其他的仍然往外抛。7. Timer.java:518:TimerThread.mainloop()从上面的代码可以看出,如果执行的任务中有其他任何运行时异常(RuntimeException)抛出,就必然导致定时器取消,也就是说挂在这个定时器上所有的人物都要被取消。明白了其内部处理机制,就要将其应用于实践,看如下例子:1. WrongTimerTask.java:2.3. package org.supermmx.example.timer;4.5. import java.util.Timer;6. import java.util.TimerTask;7.8. /*9. * Wrong timer task.10. *11. * author SuperMMX12. */13. public class WrongTimerTask extends TimerTask 14. private int count = 0;15.16. public void run() 17. System.out.println(count);18. count +;19. if (count = 3) 20. throw new NullPointerException(Test Exception);21. 22. 23.24. public static void main(String args) 25. try 26. WrongTimerTask task = new WrongTimerTask();27. Timer timer = new Timer(TestTimer);28. timer.scheduleAtFixedRate(task, 0, 1000);29. catch (Exception e) 30. e.printStackTrace();31. 32. 33. 上述代码中,每隔一秒钟打印一个递增的数值,等于 3 的时候抛一个空指针异常,结果怎么样呢?整个程序全部就退出了,就因为其中唯一的线程“TestTimer”退出了。跟前面所说的问题一模一样,只不过项目中还有很多别的线程,所以主程序并未退出。解决方法是什么呢?其实很简单,将 TimerTask 中整个 run() 方法 try 起来就可以了,保证它不再往外抛异常,代码如下:1. RightTimerTask.java:2.3. package org.supermmx.example.timer;4.5. import java.util.Timer;6. import java.util.TimerTask;7.8. /*9. * Wrong timer task.10. *11. * author SuperMMX12. */13. public class RightTimerTask extends TimerTask 14. private int count = 0;15.16. public void run() 17. try 18. System.out.println(count);19. count +;20. if (count = 3) 21. throw new NullPointerException(Test Exception);22. 23. catch (Exception e) 24. e.printStackTrace();25. 26. 27.28. public static void main(String args) 29. try 30. RightTimerTask task = new RightTimerTask();31. Timer timer = new Timer(TestTimer);32. timer.scheduleAtFixedRate(task, 0, 1000);33. catch (Exception e) 34. e.printStackTrace();35. 36. 37. 结果就是:异常也仍然抓住了,定时器也仍然可以继续工作,达到我们本来的目的。结论:使用 java.util.Timer 时候,在 java.util.TimerTask 的 run() 方法中实现具体操作的时候,必须要抓住所有异常,尤其是 RuntimeException,必须要保证不能往外抛异常,才能保证跟预想的运行情况一致。java定时器的应用举例。JAVA版本定时关机程序这个程序写的很简单,前段时间一个小MM说:从网上下载很多定时关机器都不好用,让我推荐一个。我下载了一些,觉得是不太好。当时也无聊就应承说我帮你写一个吧,功能很简单。于是java版的、粗糙的连界面都没有的定时关机器问世了。关机是利用java调用cmd来实现的,其实如果可以采用添加计划任务的方式来实现更好。不废话,上代码。MyClock.java。import java.text.DateFormat;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Scanner;import java.util.Timer;public class MyClock public String checkTime() throws ParseException System.out.println(请输入您要关机的时间,格式为mmddhhmm。例:01271010 .); Scanner sca=new Scanner(System.in); String time=sca.next(); DateFormat df=new SimpleDateFormat(yyyyMMddHHmm); Date date=df.parse(2010+time); /当输入时间在此刻之前 或者是输入字符数不对的时候再次提醒输入 while(date.before(new Date()|!time.matches(d8) date=df.parse(2010+time); System.out.println(时间输入错误,请重新输入正确时间!); time=sca.next(); return 2010+time;public static void main(String args) throws ParseException Timer timer=new Timer(); Date date=null; DateFormat df=new SimpleDateFormat(yyyyMMddHHmmss); MyClock m=new MyClock(); String str=m.checkTime()+00; date=df.parse(str); System.out.println(关机时间输入成功,程序已经启动。请勿关闭窗口。); timer.schedule(new MyTask(),date);。MyTask.java。import java.io.*;import java.util.TimerTask;public class MyTask extends TimerTask Overridepublic void run() try Process pro = Runtime.getRuntime().exec(cmd /c tsshutdn); BufferedReader br = new BufferedReader(new InputStreamReader(pro .getInputStream(); String msg = null; while (msg = br.readLine() != null) System.out.println(msg); catch (IOException exception) this.cancel(); System.exit(0);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配置文件中加入如下三行: com.test.ContextListener 当然,上面的com.test得换成您自己的包名了。保存web.xml文件后,把工程打包部署到Tomcat中即可。任务会在每晚12点至凌晨1点之间被执行。JAVA定时器使用【1】Java 定时器(java.util.Timer)有定时触发计划任务的功能,通过配置定时器的间隔时间,在某一间隔时间段之后会自动有规律的调用预先所安排的计划任务(java.util.TimerTask)。与每个 Timer 对象相对应的是单个后台线程,用于顺序地执行所有计时器任务。计时器任务应该迅速完成。如果完成某个计时器任务的时间太长,那么它会“独占”计时器的任务执行线程。因此,这就可能延迟后续任务的执行,而这些任务就可能“堆在一起”,并且在上述不友好的任务最终完成时才能够被快速连续地执行。另外,由于我们希望当Web工程启动时,定时器能自动开始计时,在整个Web工程的生命期里,定时器能在每晚深夜触发一次报表计算引擎天等。因此定时器的存放位置也值得考查,不能简单的存在于单个Servlet或JavaBean中,必须能让定时器宿主的存活期为整个Web工程生命期,在工程启动时能自动加载运行。结合这两点,跟Servlet上下文有关的监听器就最合适不过了,通过在工程的配置文件中加以 合理配置,会在工程启动时自动运行,并在整个工程生命期中处于监听状态。 下面就Servlet监听器结合Java 定时器来讲述整个实现过程。要运用Servlet监听器需要实现javax.servlet.ServletContextListener接口,同时实现它的contextInitialized(ServletContextEvent event)和contextDestroyed(ServletContextEvent event)两个接口函数。考虑定时器有个建立和销毁的过程,看了前面两个接口函数,就不容置疑的把建立的过程置入 contextInitialized,把销毁的过程置入contextDestroyed了。package com.korby.servlet;import javax.servlet.*;import javax.servlet.http.*;import com.korby.pub.TimerManager;/* 启动定时器的监听器* author korby* version 1.0*/public class TimerListener implements ServletContextListener private TimerManager tm = null; public void contextInitialized(ServletContextEvent sce) int day,hour,min,sec; day = 26; hour = 16; min = 42; sec = 0; tm = new TimerManager(day,hour,min,sec); public void contextDestroyed(ServletContextEvent sce) tm.destoryTimer(); package com.korby.pub;import java.util.Timer;import java.util.Date;import java.util.Calendar;/* 定时器* author korby* version 1.0*/public class TimerManager Timer t = null; public TimerManager(int day,int hour,int min,int sec) time(day,hour,min,sec); public void time(int day,int hour,int min,int sec) Calendar c = Calendar.getInstance(); c.set(Calendar.DAY_OF_MONTH,day); c.set(Calendar.HOUR_OF_DAY,hour); c.set(Calendar.MINUTE,min); c.set(Calendar.SECOND,sec); Date date = c.getTime(); System.out.println(c.getTime(); t= new Timer(); MyTask mt = new MyTask(); t.schedule(mt, date); public void destoryTimer() t.cancel(); package com.korby.pub;import java.util.TimerTask;/* 计划任务代码* author korby* version 1.0*/public class MyTask extends TimerTask public MyTask() /* * 任务块 */ public void run() System.out.println(定时器RUN); 在web.xml中设置一个监听器: com.korby.servlet.TimerListener【2】 java.util.Timervoid cancel()终止此计时器,丢弃所有当前已安排的任务。int purge() 从此计时器的任务队列中移除所有已取消的任务。void schedule(TimerTask task,Date time)安排在指定的时间执行指定的任务。void schedule(TimerTask task,Date firstTime, long period)安排指定的任务在指定的时间开始进行重复的固定延迟执行。void schedule(TimerTask task,long delay)安排在指定延迟后执行指定的任务。void schedule(TimerTask task,long delay, long period)安排指定的任务从指定的延迟后开始进行重复的固定延迟执行。void schedule(TimerTask task,long delay, long period)安排指定的任务从指定的延迟后开始进行重复的固定延迟执行。void scheduleAtFixedRate(TimerTask task,long delay, long period)安排指定的任务在指定的延迟后开始进行重复的固定速率执行。【3】java.util.TimerTask由 Timer 安排为一次执行或重复执行的任务。boolean cancel() 取消此计时器任务。abstract void run() 此计时器任务要执行的操作。long scheduledExecutionTime() 返回此任务最近实际 执行的已安排 执行时间。Java定时器状态错误:【java.lang.IllegalStateException: Timer already cancelled.】10-3-5 13:14:41:729 CST 1dd900b SystemErr R java.lang.IllegalStateException: Timer already cancelled.10-3-5 13:14:41:731 CST 1dd900b SystemErr R at java.util.Timer.sched(Timer.java:312)10-3-5 13:14:41:731 CST 1dd900b SystemErr R at java.util.Timer.schedule(Timer.java:180)10-3-5 13:14:41:731 CST 1dd900b SystemErr R at com.yourcompany.businesscomponent.utils.TimerRetrieveDb2Data.main(TimerRetrieveDb2Data.java:37)10-3-5 13:14:41:731 CST 1dd900b SystemErr R at com.yourcompany.businesscomponent.service.YourBusinessNameFromDb2Service.controlTimerInManual(YourBusinessNameFromDb2Service.java:179)10-3-5 13:14:41:731 CST 1dd900b SystemErr R at com.yourcompany.businesscomponent.action.YourBusinessNameAction.controlInManual(YourBusinessNameAction.java:617)10-3-5 13:14:41:731 CST 1dd900b SystemErr R at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)10-3-5 13:14:41:731 CST 1dd900b SystemErr R at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)10-3-5 13:14:41:732 CST 1dd900b SystemErr R at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)10-3-5 13:14:41:732 CST 1dd900b SystemErr R at java.lang.reflect.Method.invoke(Method.java:324)10-3-5 13:14:41:732 CST 1dd900b SystemErr R at org.apache.struts.actions.DispatchAction.dispatchMethod(DispatchAction.java:280)10-3-5 13:14:41:732 CST 1dd900b SystemErr R at org.apache.struts.actions.DispatchAction.execute(DispatchAction.java:216)10-3-5 13:14:41:732 CST 1

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论