- 浏览: 106514 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
ynnuyili:
...
在datagrid中的toolbar添加输入框 -
k_kid9157:
很棒! 学习了感谢分享!
ExtJs tree 静态树(从本地获取数据源) -
火大了:
...
在datagrid中的toolbar添加输入框
简介:这是实现定时器的详细页面,介绍了和java,有关的知识、技巧、经验,和一些java源码等。
1、在应用开发中,经常需要一些周期性的操作,比如每5分钟检查一下新邮件等。对于这样的操作最方便、高效的实现方式就是使用java.util.Timer工具类。比如下面的代码每5分钟检查一遍是否有新邮件:
使用这几行代码之后,Timer本身会每隔5分钟调用一遍server.checkNewMail()方法,不需要自己启动线程。Timer本身也是多线程同步的,多个线程可以共用一个Timer,不需要外部的同步代码。
在《The Java Tutorial》中有更完整的例子:
这段程序,每隔3秒响铃一声,并打印出一行消息。循环3次。程序输出如下:
IWAV0048I Java Bean com.AnnoyingBeep started with null constructor
Task scheduled.
Beep!
Beep! //one second after the first beep
Beep! //one second after the second beep
Time´s up! //one second after the third beep
Timer类也可以方便地用来作为延迟执行,比如下面的代码延迟指定的时间(以秒为单位)执行某操作。类似电视的延迟关机功能。
2、下面再写一个在WEB下定时器
由于系统核心是基于Web部署的,报表计算引擎也相应的部署在Tomcat容器上,因此如果想要借用Windows的任务计划来实现定时计算,就需要额外编写普通桌面应用程序接口,稍显复杂。于是就琢磨着想在Web上实现,经过查阅较多相关资料,发现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了。
我把ServletContextListener的实现类取名为ContextListener,在其内添加一个定时器,示例代码如下所示(为考虑篇幅,仅提供部分代码供读者参考):
以上代码中, 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配置文件中加入如下三行:
com.test.ContextListener
当然,上面的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 指定任务执行结束
由于系统核心是基于Web部署的,报表计算引擎也相应的部署在Tomcat容器上,因此如果想要借用Windows的任务计划来实现定时计算,就需要额外编写普通桌面应用程序接口,稍显复杂。于是就琢磨着想在Web上实现,经过查阅较多相关资料,发现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了。
我把ServletContextListener的实现类取名为ContextListener,在其内添加一个定时器,示例代码如下所示(为考虑篇幅,仅提供部分代码供读者参考):
1. private java.util.Timer timer = null;
2. public void contextInitialized(ServletContextEvent event) {
3. timer = new java.util.Timer(true);
4. event.getServletContext().log(“定时器已启动”);
5. timer.schedule(new MyTask(event.getServletContext()), 0, 60*60*1000);
6. event.getServletContext().log(“已经添加任务调度表”);
7. }
8. public void contextDestroyed(ServletContextEvent event) {
9. timer.cancel();
10. event.getServletContext().log(“定时器销毁”);
11. }
以上代码中, 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。示例代码如下所示:
1. private static final int C_SCHEDULE_HOUR = 0;
2. private static boolean isRunning = false;
3. private ServletContext context = null;
4. public MyTask(ServletContext context) {
5. this.context = context;
6. }
7. public void run() {
8. Calendar cal = Calendar.getInstance();
9. if (!isRunning) {
10. if (C_SCHEDULE_HOUR == cal.get(Calendar.HOUR_OF_DAY)) {
11. isRunning = true;
12. context.log(“开始执行指定任务”);
13.
14. //TODO 添加自定义的详细任务,以下只是示例
15. int i = 0;
16. while (i++ < 10) {
17. context.log(“已完成任务的” + i + ”/” + 10);
18. }
19.
20. isRunning = false;
21. context.log(“指定任务执行结束”);
22. }
23. } else {
24. context.log(“上一次任务执行还未结束”);
25. }
26. }
上面代码中“//TODO……”之下四行是真正被调度执行的演示代码(在我的财政数据中心项目中就是报表计算过程),您可以换成自己希望执行的语句。
到这儿,ServletContextListener和MyTask的代码都已完整了。最后一步就是把ServletContextListener部署到您的Web工程中去,在您工程的web.xml配置文件中加入如下三行:
com.test.ContextListener
当然,上面的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 指定任务执行结束
3、实现定时
public class myTask
extends java.util.TimerTask {
String jobName;
private int i;
public void run() { //run in interface Runnable
System.out.println(jobName);
}
public myTask(String jobName) {
this.jobName = jobName;
}
}
//doTask.java
import java.util.*;
import java.io.*;
public class doTask {
private java.util.Timer timer;
private java.util.TimerTask task;
public doTask(java.util.TimerTask task) {
this.timer = new Timer();
this.task = task;
}
public void start(int delay, int internal) {
timer.schedule(task, delay * 1000, internal * 1000);//利用timer.schedule方法
}
public static void main(String[] args) {
java.util.TimerTask task1 = new myTask(” Job 1″);
java.util.TimerTask task2= new myTask(“Job 2″);
doTask pt = new doTask(task1);
pt.start(1,3);
doTask pt2 = new doTask(task2);
pt2.start(1,1);
}
}
4、C#结合singleton和线程做一个定时服务
design pattern的singleton是一个虽然简单但很有用处的模式,它的作用就是使类只能有一个实例,不需要实例化,而提供一个唯一的全局切入点。如果再结合上线程,完全可以实现一个定时服务,不象Timer控件,它不仅可以应用在windows应用程序中,同样可以应用于web程序中,就象刚才蓝说的那种效果。看下面这个简单的例子吧。
using System;
using System.Threading ;
namespace testall
{
/// <summary>
/// 定时间隔
/// </summary>
/// <remarks>通过修改这个常量决定间隔多长时间做某件事</remarks>
const int DELAY_TIMES = 1000 ;
/// <summary>
/// 一个计数器
/// </summary>
private int m_intCounter = 0;
/// <summary>
/// 是否退出
/// </summary>
private bool m_bCanExit = false ;
/// <summary>
/// 线程
/// </summary>
private Thread thread ;
/// <summary>
/// 自身实例
/// </summary>
/// <remarks>注意,这是实现singleton的关键</remarks>
private static TestStatic instance = new TestStatic() ;
public int Counter
{
get
{
return this.m_intCounter ;
}
set
{
this.m_intCounter = value ;
}
}
public bool CanExit
{
set
{
this.m_bCanExit = value ;
}
}
/// <summary>
/// 构造函数
/// </summary>
public TestStatic()
{
//
// TODO: Add constructor logic here
//
this.m_intCounter = 0 ;
Console.WriteLine(“constructor is running”) ;
this.thread = new Thread(new ThreadStart(ThreadProc)) ;
thread.Name = “online user” ;
thread.Start() ;
Console.WriteLine(“完毕”) ;
}
/// <summary>
/// 实现singleton的关键
/// </summary>
/// <returns>类本身的一个实例</returns>
/// <remarks>唯一的全局切入点</remarks>
public static TestStatic GetInstance()
{
return instance ;
}
/// <summary>
/// 线程工作函数
/// </summary>
/// <remarks>想做什么写在这儿</remarks>
private void ThreadProc()
{
while(!this.m_bCanExit)
{
this.m_intCounter ++ ;
Console.WriteLine(this.m_intCounter.ToString()) ;
Thread.Sleep(DELAY_TIMES) ;
}
}
static void Main(string[] args)
{
//
// TODO: Add code to start application here
//
Console.WriteLine(TestStatic.GetInstance().Counter.ToString()) ;
Console.Read() ;
TestStatic.GetInstance().CanExit = true ;
}
}
}
//////////////////////////////////////////////////////////////////////
import java.util.TimerTask;
import java.util.Calendar;
public class MyTask extends TimerTask
{
private static final int C_SCHEDULE_HOUR = 15;
private static boolean isRunning = false;
public MyTask()
{
}
public void run()
{
Calendar cal = Calendar.getInstance();
if (!isRunning)
{
//if (C_SCHEDULE_HOUR == cal.get(Calendar.HOUR_OF_DAY))
{
isRunning = true;
System.out.println(new java.util.Date() + ” 任务开始”);
for (int i = 0 ; i < 100 ; i++ )
{
System.out.println(new java.util.Date() + ” 任务完成” + i + ”/” + 100 );
}
isRunning = false;
System.out.println(new java.util.Date() + ” 所有任务完成!”);
}
}
else
{
System.out.println(new java.util.Date() + ” 任务退出!!!”);
}
}
}
=====================================Test===========================================
import java.util.TimerTask;
import java.util.Timer;
import javax.servlet.*;
public class Test{
static Timer timer = null;
public static void main(String[] args){
timer = new Timer(true);
System.out.println(new java.util.Date() + ” 计时器已经启动…”);
timer.schedule(new MyTask() , 0 , 2*60*1000);//每2分钟执行一次
System.out.println(new java.util.Date() + ” 计时器执行一次!!!!!”);
}
}
//////////////////////////////////////////////////////////////////////
JAVA-如何实现TIMER功能
2004-11-8
Author :Meanson Wang
Email:meansonw@hotmail.com
Date:2004-11-8
JAVA里面要实现日程管理[每天或每月的某时执行某个任务],可以用timer和TimerTask来实现。
本文会介绍如何实现一个日程的方法。这里会设计两个类,一个侦听类,用来定时执行任务[可执行多个任务].一个任务类,用来调用任务.以下是实现每天15:00执行一个任务.
1.listener class
package timer;
import java.util.TimerTask;
import java.util.Timer;
import javax.servlet.*;
public class RemindListener implements ServletContextListener {
private java.util.Timer timer = null;
public void contextInitialized(ServletContextEvent sce) {
timer = new java.util.Timer(true);
sce.getServletContext().log(new java.util.Date()+”Timer start up!”);
timer.schedule(new RemindTask(),0,60*60*1000);//every 60 minute roll
sce.getServletContext().log(new java.util.Date()+”Schedule loaded!”);
}
public void contextDestroyed(ServletContextEvent sce) {
timer.cancel();
sce.getServletContext().log(new java.util.Date()+”Timer destroyed!”);
}
}
2.Task class
package timer;
import java.util.TimerTask;
import java.util.Calendar;
public class RemindTask extends TimerTask{
private static final int C_SCHEDULE_HOUR = 15;
private static boolean isRunning = false;
public RemindTask() {
}
public void run() {
Calendar cal = Calendar.getInstance();
if (!isRunning) {
if (C_SCHEDULE_HOUR == cal.get(Calendar.HOUR_OF_DAY)) {
isRunning = true;
System.out.println(new java.util.Date()+”task start”);
//TODO for example
int i = 0;
while (i++ < 10) {
System.out.println(new java.util.Date()+”Done!task” + i + ”/” + 10);
}
isRunning = false;
System.out.println(new java.util.Date()+”All task Done!”);
}
}
else
{
System.out.println(new java.util.Date()+”Task existed!”);
}
}
}
3.loadonstart in web.xml
<listener>
<listener-class>timer.RemindListener</listener-class>
</listener>
4.restart server
注意:当您为您的应用设置了虚拟机,定时器会启动两个.任务会执行两次!我的解决方法是为日程管理另起一个应用.
//////////////////////////////////////////////////////////////////////
使用定时器,定时执行任务
import java.util.Timer;
import java.util.TimerTask;
public class Test
{
public static void main(String args[])
{
final Timer timer = new Timer();
timer.scheduleAtFixedRate(new TTask(),5000,1000);
}
}
class TTask extends TimerTask
{
public void run()
{
System.out.println(“hello”);
}
}
////////////////////////////////////////////////////////////////////////
在Java中实现Job Scheduling
在大多数项目中,在特定的时间或频率下你需要完成一些特定的任务。在本文中我们将演示如何用标准的Java Timer API来实现。
大多商业应用都会用报表和统计,很难想象没有这些帮助我们分析未来趋势的数据,我们还要这系统干什么。问题是如此多的数据我们该如何触发,如果处理对系统性能影响不大。比较好的方式是避开应用高峰,让服务器在闲暇时完成这些事。
下面是我的程序:
import java.util.TimerTask;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
public class ReportGenerator extends TimerTask{
/* (非 Javadoc)
* @see java.util.TimerTask#run()
*/
public void run() {
System.out.println(“Generating report”);
}
}
class MainApplication {
public static void main(String[] args) {
Timer timer=new Timer();
Calendar date = Calendar.getInstance();
date.set(
Calendar.DAY_OF_WEEK,
Calendar.SUNDAY
);
date.set(Calendar.HOUR, 0);
date.set(Calendar.MINUTE, 0);
date.set(Calendar.SECOND, 0);
date.set(Calendar.MILLISECOND, 0);
// Schedule to run every Sunday in midnight
timer.schedule(
new ReportGenerator(),
date.getTime(),
1000 * 60 * 60 * 24 * 7
);
}
}
我先简单解释一下,在我们的例子中ReportGenerator继承java.util.TimerTask,它又继承了java.lang.Runnable,我们需要覆盖run()方法。
调用时我们用schedule()方法让它每周日0点0分执行,避开服务器高峰,实现Job Scheduling的目的。
原文转自:http://www.dnbcw.com/biancheng/java/sfwm299870.html
http://www.ij2ee.com/2011/02/28/%E5%AE%9E%E7%8E%B0%E5%AE%9A%E6%97%B6%E5%99%A8.html
1、在应用开发中,经常需要一些周期性的操作,比如每5分钟检查一下新邮件等。对于这样的操作最方便、高效的实现方式就是使用java.util.Timer工具类。比如下面的代码每5分钟检查一遍是否有新邮件:
private java.util.Timer timer; timer = new Timer(true); timer.schedule( new java.util.TimerTask() { public void run() { //server.checkNewMail(); 检查新邮件 } }, 0, 5*60*1000);
使用这几行代码之后,Timer本身会每隔5分钟调用一遍server.checkNewMail()方法,不需要自己启动线程。Timer本身也是多线程同步的,多个线程可以共用一个Timer,不需要外部的同步代码。
在《The Java Tutorial》中有更完整的例子:
public class AnnoyingBeep { Toolkit toolkit; Timer timer; public AnnoyingBeep() { toolkit = Toolkit.getDefaultToolkit(); timer = new Timer(); timer.schedule(new RemindTask(), 0, 1*1000); //initial delay subsequent rate } class RemindTask extends TimerTask { int numWarningBeeps = 3; public void run() { if (numWarningBeeps > 0) { toolkit.beep(); System.out.println(“Beep!”); numWarningBeeps–; } else { toolkit.beep(); System.out.println(“Time´s up!”); //timer.cancel(); //Not necessary because we call System.exit System.exit(0); //Stops the AWT thread (and everything else) } } } … }
这段程序,每隔3秒响铃一声,并打印出一行消息。循环3次。程序输出如下:
IWAV0048I Java Bean com.AnnoyingBeep started with null constructor
Task scheduled.
Beep!
Beep! //one second after the first beep
Beep! //one second after the second beep
Time´s up! //one second after the third beep
Timer类也可以方便地用来作为延迟执行,比如下面的代码延迟指定的时间(以秒为单位)执行某操作。类似电视的延迟关机功能。
…public class ReminderBeep { … public ReminderBeep(int seconds) { toolkit = Toolkit.getDefaultToolkit(); timer = new Timer(); timer.schedule(new RemindTask(), seconds*1000); } class RemindTask extends TimerTask { public void run() { System.out.println(“Time´s up!”); toolkit.beep(); //timer.cancel(); //Not necessary because we call System.exit System.exit(0); //Stops the AWT thread (and everything else) } } … } }
2、下面再写一个在WEB下定时器
由于系统核心是基于Web部署的,报表计算引擎也相应的部署在Tomcat容器上,因此如果想要借用Windows的任务计划来实现定时计算,就需要额外编写普通桌面应用程序接口,稍显复杂。于是就琢磨着想在Web上实现,经过查阅较多相关资料,发现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了。
我把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配置文件中加入如下三行:
com.test.ContextListener
当然,上面的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 指定任务执行结束
由于系统核心是基于Web部署的,报表计算引擎也相应的部署在Tomcat容器上,因此如果想要借用Windows的任务计划来实现定时计算,就需要额外编写普通桌面应用程序接口,稍显复杂。于是就琢磨着想在Web上实现,经过查阅较多相关资料,发现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了。
我把ServletContextListener的实现类取名为ContextListener,在其内添加一个定时器,示例代码如下所示(为考虑篇幅,仅提供部分代码供读者参考):
1. private java.util.Timer timer = null;
2. public void contextInitialized(ServletContextEvent event) {
3. timer = new java.util.Timer(true);
4. event.getServletContext().log(“定时器已启动”);
5. timer.schedule(new MyTask(event.getServletContext()), 0, 60*60*1000);
6. event.getServletContext().log(“已经添加任务调度表”);
7. }
8. public void contextDestroyed(ServletContextEvent event) {
9. timer.cancel();
10. event.getServletContext().log(“定时器销毁”);
11. }
以上代码中, 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。示例代码如下所示:
1. private static final int C_SCHEDULE_HOUR = 0;
2. private static boolean isRunning = false;
3. private ServletContext context = null;
4. public MyTask(ServletContext context) {
5. this.context = context;
6. }
7. public void run() {
8. Calendar cal = Calendar.getInstance();
9. if (!isRunning) {
10. if (C_SCHEDULE_HOUR == cal.get(Calendar.HOUR_OF_DAY)) {
11. isRunning = true;
12. context.log(“开始执行指定任务”);
13.
14. //TODO 添加自定义的详细任务,以下只是示例
15. int i = 0;
16. while (i++ < 10) {
17. context.log(“已完成任务的” + i + ”/” + 10);
18. }
19.
20. isRunning = false;
21. context.log(“指定任务执行结束”);
22. }
23. } else {
24. context.log(“上一次任务执行还未结束”);
25. }
26. }
上面代码中“//TODO……”之下四行是真正被调度执行的演示代码(在我的财政数据中心项目中就是报表计算过程),您可以换成自己希望执行的语句。
到这儿,ServletContextListener和MyTask的代码都已完整了。最后一步就是把ServletContextListener部署到您的Web工程中去,在您工程的web.xml配置文件中加入如下三行:
com.test.ContextListener
当然,上面的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 指定任务执行结束
3、实现定时
public class myTask
extends java.util.TimerTask {
String jobName;
private int i;
public void run() { //run in interface Runnable
System.out.println(jobName);
}
public myTask(String jobName) {
this.jobName = jobName;
}
}
//doTask.java
import java.util.*;
import java.io.*;
public class doTask {
private java.util.Timer timer;
private java.util.TimerTask task;
public doTask(java.util.TimerTask task) {
this.timer = new Timer();
this.task = task;
}
public void start(int delay, int internal) {
timer.schedule(task, delay * 1000, internal * 1000);//利用timer.schedule方法
}
public static void main(String[] args) {
java.util.TimerTask task1 = new myTask(” Job 1″);
java.util.TimerTask task2= new myTask(“Job 2″);
doTask pt = new doTask(task1);
pt.start(1,3);
doTask pt2 = new doTask(task2);
pt2.start(1,1);
}
}
4、C#结合singleton和线程做一个定时服务
design pattern的singleton是一个虽然简单但很有用处的模式,它的作用就是使类只能有一个实例,不需要实例化,而提供一个唯一的全局切入点。如果再结合上线程,完全可以实现一个定时服务,不象Timer控件,它不仅可以应用在windows应用程序中,同样可以应用于web程序中,就象刚才蓝说的那种效果。看下面这个简单的例子吧。
using System;
using System.Threading ;
namespace testall
{
/// <summary>
/// 定时间隔
/// </summary>
/// <remarks>通过修改这个常量决定间隔多长时间做某件事</remarks>
const int DELAY_TIMES = 1000 ;
/// <summary>
/// 一个计数器
/// </summary>
private int m_intCounter = 0;
/// <summary>
/// 是否退出
/// </summary>
private bool m_bCanExit = false ;
/// <summary>
/// 线程
/// </summary>
private Thread thread ;
/// <summary>
/// 自身实例
/// </summary>
/// <remarks>注意,这是实现singleton的关键</remarks>
private static TestStatic instance = new TestStatic() ;
public int Counter
{
get
{
return this.m_intCounter ;
}
set
{
this.m_intCounter = value ;
}
}
public bool CanExit
{
set
{
this.m_bCanExit = value ;
}
}
/// <summary>
/// 构造函数
/// </summary>
public TestStatic()
{
//
// TODO: Add constructor logic here
//
this.m_intCounter = 0 ;
Console.WriteLine(“constructor is running”) ;
this.thread = new Thread(new ThreadStart(ThreadProc)) ;
thread.Name = “online user” ;
thread.Start() ;
Console.WriteLine(“完毕”) ;
}
/// <summary>
/// 实现singleton的关键
/// </summary>
/// <returns>类本身的一个实例</returns>
/// <remarks>唯一的全局切入点</remarks>
public static TestStatic GetInstance()
{
return instance ;
}
/// <summary>
/// 线程工作函数
/// </summary>
/// <remarks>想做什么写在这儿</remarks>
private void ThreadProc()
{
while(!this.m_bCanExit)
{
this.m_intCounter ++ ;
Console.WriteLine(this.m_intCounter.ToString()) ;
Thread.Sleep(DELAY_TIMES) ;
}
}
static void Main(string[] args)
{
//
// TODO: Add code to start application here
//
Console.WriteLine(TestStatic.GetInstance().Counter.ToString()) ;
Console.Read() ;
TestStatic.GetInstance().CanExit = true ;
}
}
}
//////////////////////////////////////////////////////////////////////
import java.util.TimerTask;
import java.util.Calendar;
public class MyTask extends TimerTask
{
private static final int C_SCHEDULE_HOUR = 15;
private static boolean isRunning = false;
public MyTask()
{
}
public void run()
{
Calendar cal = Calendar.getInstance();
if (!isRunning)
{
//if (C_SCHEDULE_HOUR == cal.get(Calendar.HOUR_OF_DAY))
{
isRunning = true;
System.out.println(new java.util.Date() + ” 任务开始”);
for (int i = 0 ; i < 100 ; i++ )
{
System.out.println(new java.util.Date() + ” 任务完成” + i + ”/” + 100 );
}
isRunning = false;
System.out.println(new java.util.Date() + ” 所有任务完成!”);
}
}
else
{
System.out.println(new java.util.Date() + ” 任务退出!!!”);
}
}
}
=====================================Test===========================================
import java.util.TimerTask;
import java.util.Timer;
import javax.servlet.*;
public class Test{
static Timer timer = null;
public static void main(String[] args){
timer = new Timer(true);
System.out.println(new java.util.Date() + ” 计时器已经启动…”);
timer.schedule(new MyTask() , 0 , 2*60*1000);//每2分钟执行一次
System.out.println(new java.util.Date() + ” 计时器执行一次!!!!!”);
}
}
//////////////////////////////////////////////////////////////////////
JAVA-如何实现TIMER功能
2004-11-8
Author :Meanson Wang
Email:meansonw@hotmail.com
Date:2004-11-8
JAVA里面要实现日程管理[每天或每月的某时执行某个任务],可以用timer和TimerTask来实现。
本文会介绍如何实现一个日程的方法。这里会设计两个类,一个侦听类,用来定时执行任务[可执行多个任务].一个任务类,用来调用任务.以下是实现每天15:00执行一个任务.
1.listener class
package timer;
import java.util.TimerTask;
import java.util.Timer;
import javax.servlet.*;
public class RemindListener implements ServletContextListener {
private java.util.Timer timer = null;
public void contextInitialized(ServletContextEvent sce) {
timer = new java.util.Timer(true);
sce.getServletContext().log(new java.util.Date()+”Timer start up!”);
timer.schedule(new RemindTask(),0,60*60*1000);//every 60 minute roll
sce.getServletContext().log(new java.util.Date()+”Schedule loaded!”);
}
public void contextDestroyed(ServletContextEvent sce) {
timer.cancel();
sce.getServletContext().log(new java.util.Date()+”Timer destroyed!”);
}
}
2.Task class
package timer;
import java.util.TimerTask;
import java.util.Calendar;
public class RemindTask extends TimerTask{
private static final int C_SCHEDULE_HOUR = 15;
private static boolean isRunning = false;
public RemindTask() {
}
public void run() {
Calendar cal = Calendar.getInstance();
if (!isRunning) {
if (C_SCHEDULE_HOUR == cal.get(Calendar.HOUR_OF_DAY)) {
isRunning = true;
System.out.println(new java.util.Date()+”task start”);
//TODO for example
int i = 0;
while (i++ < 10) {
System.out.println(new java.util.Date()+”Done!task” + i + ”/” + 10);
}
isRunning = false;
System.out.println(new java.util.Date()+”All task Done!”);
}
}
else
{
System.out.println(new java.util.Date()+”Task existed!”);
}
}
}
3.loadonstart in web.xml
<listener>
<listener-class>timer.RemindListener</listener-class>
</listener>
4.restart server
注意:当您为您的应用设置了虚拟机,定时器会启动两个.任务会执行两次!我的解决方法是为日程管理另起一个应用.
//////////////////////////////////////////////////////////////////////
使用定时器,定时执行任务
import java.util.Timer;
import java.util.TimerTask;
public class Test
{
public static void main(String args[])
{
final Timer timer = new Timer();
timer.scheduleAtFixedRate(new TTask(),5000,1000);
}
}
class TTask extends TimerTask
{
public void run()
{
System.out.println(“hello”);
}
}
////////////////////////////////////////////////////////////////////////
在Java中实现Job Scheduling
在大多数项目中,在特定的时间或频率下你需要完成一些特定的任务。在本文中我们将演示如何用标准的Java Timer API来实现。
大多商业应用都会用报表和统计,很难想象没有这些帮助我们分析未来趋势的数据,我们还要这系统干什么。问题是如此多的数据我们该如何触发,如果处理对系统性能影响不大。比较好的方式是避开应用高峰,让服务器在闲暇时完成这些事。
下面是我的程序:
import java.util.TimerTask;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
public class ReportGenerator extends TimerTask{
/* (非 Javadoc)
* @see java.util.TimerTask#run()
*/
public void run() {
System.out.println(“Generating report”);
}
}
class MainApplication {
public static void main(String[] args) {
Timer timer=new Timer();
Calendar date = Calendar.getInstance();
date.set(
Calendar.DAY_OF_WEEK,
Calendar.SUNDAY
);
date.set(Calendar.HOUR, 0);
date.set(Calendar.MINUTE, 0);
date.set(Calendar.SECOND, 0);
date.set(Calendar.MILLISECOND, 0);
// Schedule to run every Sunday in midnight
timer.schedule(
new ReportGenerator(),
date.getTime(),
1000 * 60 * 60 * 24 * 7
);
}
}
我先简单解释一下,在我们的例子中ReportGenerator继承java.util.TimerTask,它又继承了java.lang.Runnable,我们需要覆盖run()方法。
调用时我们用schedule()方法让它每周日0点0分执行,避开服务器高峰,实现Job Scheduling的目的。
原文转自:http://www.dnbcw.com/biancheng/java/sfwm299870.html
http://www.ij2ee.com/2011/02/28/%E5%AE%9E%E7%8E%B0%E5%AE%9A%E6%97%B6%E5%99%A8.html
发表评论
-
dwr demo
2017-12-05 09:57 498<div class="iteye-blog ... -
HttpClient example 学习一(快速开始)
2013-03-26 12:47 1302package org.apache.http.exampl ... -
java string/string[]转换成integer/long
2011-06-07 16:06 31421、String 转换成 float/int Stri ... -
java产生随机数
2011-05-27 03:45 1464java产生随机数 Date date = new D ... -
java 动态创建数据库和动态连接数据库
2011-05-22 21:07 6017项目中有一个需求要动态创建数据库并且要动态连接数据库,本来以为 ... -
j2ee定时器
2011-05-01 19:34 873http://hjkx180.blog.163.com/blo ... -
定时器
2011-05-01 19:27 1154我想在WebLogic下实现定时器的功能, 即:在某一固定时间 ... -
java通过url在线预览Word、excel、ppt、pdf、txt文档中的内容
2011-04-14 14:54 3669在页面上显示各种文档中的内容。在servlet中的逻辑 wo ...
相关推荐
C#多线程实现定时器 C#多线程实现定时器是指使用C#语言中的多线程编程技术来实现定时器功能。定时器是指在一定的时间间隔内执行某个操作或函数的机制。在C#中,可以使用System.Windows.Forms.Timer控件来实现定时器...
本篇文章将详细探讨如何在MFC中利用多线程来实现定时器。 首先,我们需要了解MFC中的`CWinThread`类,它是所有线程的基础类。创建一个新的线程时,通常会从`CWinThread`派生一个类,并重写其`Run`成员函数,这个...
本例程详细阐述了如何利用PCA实现定时器的全过程,包括初始化设置、中断处理等关键环节,对于学习和理解51单片机的PCA功能以及如何在实际项目中运用PCA具有重要的参考价值。通过深入学习和实践,开发者可以更好地...
本项目重点讨论的是如何在LabVIEW中实现定时器功能以及获取当前的时间日期。 ### 1. LabVIEW定时器的类型 在LabVIEW中,有几种常见的定时器类型: - **连续定时器**:一旦启动,将周期性地触发事件,直到被停止。...
在本项目中,我们关注的是如何在FPGA(Field Programmable Gate Array)MPSoC(Multi-Processor System on Chip)平台上实现定时器中断,具体使用了Xilinx的VITIS工具进行开发。VITIS是Xilinx推出的一套综合开发环境...
"STM32 实现定时器类"这个主题就是关于如何在STM32的软件开发中,创建一个通用的定时器类,以便在不同文件中方便地使用定时功能,避免了直接操作硬件定时器的复杂性。 首先,我们要理解STM32中的定时器类型。STM32...
Quartus实现定时器和3位循环码计数器的设计与实现 本资源主要介绍了使用Quartus II工具实现定时器和3位循环码计数器的设计和实现过程。下面是对该资源的详细解释和知识点总结: Quartus II简介 Quartus II是一个...
在Linux系统中,线程实现定时器是一种常见的技术,它涉及到多线程编程、时间管理以及C语言编程。本文将深入探讨如何使用C语言在Linux环境下编写线程定时器的源码,同时会涵盖相关标签所涉及的关键概念。 首先,我们...
在本文中,我们将深入探讨如何使用Qt5.9.1框架来实现定时器功能。Qt是一个跨平台的应用程序开发框架,广泛应用于桌面、移动和嵌入式设备的GUI设计。定时器是Qt库中的一个重要组件,它允许开发者在特定时间间隔执行...
"Excel 实现定时器功能" 在 Excel 中,用户可以通过 VBA 实现自动定时运行操作。尽管 Excel VBA 没有提供定时器控件,但是用户可以通过 Application 对象的 OnTime 方法实现简单的定时器功能。 在 StartTimer 过程...
本文将详细讲解如何在基于ARM7架构的LPC2136微控制器上,利用SPI功能来实现定时器的功能。LPC2136是一款功能丰富的微控制器,具有多个定时器单元和集成的SPI接口,适用于各种实时应用。 **一、SPI接口详解** SPI...
本项目" FPGA XC7A100T实现定时器驱动(Microblaze实现)"主要涉及到的是在Microblaze处理器上开发一个定时器驱动程序。定时器在嵌入式系统中起着至关重要的作用,它可以用于任务调度、中断服务、脉冲产生等多种功能...
本文将详细探讨两种常见的嵌入式软件实现定时器的方法:硬件定时器和软件定时器。 一、硬件定时器 硬件定时器是微处理器内部或外部的一种专用硬件资源,它通过计数器对系统时钟脉冲进行计数,当达到预设值时产生...
本文将详细探讨如何使用单片机实现定时器门铃的设计。 首先,我们需要了解单片机的基本结构。单片机通常包括CPU、存储器(ROM和RAM)、定时/计数器、输入/输出接口等组成部分。其中,定时/计数器是实现定时器功能的...
本篇将详细讲解如何在线程内部使用`SetTimer`来实现定时器,以及`MyThreadTimer`的实现方式。 首先,理解`SetTimer`函数的基本用法。`SetTimer`的原型如下: ```cpp UINT_PTR SetTimer( _In_opt_ HWND hWnd, _In...
本项目提供的"EP4CE10实现定时器IP核(Nios_II实现)"压缩包包含了完整的硬件设计文件、Nios_II处理器配置、软件驱动程序和编译运行指南。通过学习这个项目,开发者不仅可以掌握FPGA上的定时器设计,还能熟悉Nios_II...
在本项目中,我们主要探讨的是如何在Xilinx的FPGA MPSoC平台上,利用VITIS工具实现定时器中断的功能。Xilinx的Zynq UltraScale+ MPSoC系列,如XCZU2CG、XCZU2EG和XCZU4EV,集成了可编程逻辑(FPGA部分)和处理器系统...
本文将详细阐述如何在基于NXP的i.MX6ULL微处理器上实现定时器中断的裸机驱动。i.MX6ULL是一款低功耗、高性能的应用处理器,广泛应用于各种嵌入式设备,如物联网(IoT)设备、工业控制和多媒体应用等。 首先,我们需要...
在本项目中,我们将关注ZYNQ 7020的SDK驱动程序,特别是如何实现定时器驱动。 SDK(Software Development Kit)是Xilinx提供的软件开发环境,用于为ZYNQ SoC开发应用层软件。它包含了一个集成开发环境(IDE),支持...
在本项目中,我们关注的是如何利用Xilinx的FPGA MPSoC器件,特别是XCZU4EV型号,实现定时器中断功能,并且这个过程是基于VITIS平台进行的。VITIS(Xilinx Versal™ 和 Zynq® UltraScale+™ MPSoC嵌入式软件开发平台...