文章说明:http://blog.csdn.net/sessionsong/article/details/50516320
Java web 项目中 简单定时器实现 Timer
项目背景: 系统中有一个存放压缩文件的临时文件夹。当时间长了后 存放文件多了,占用磁盘空间过大 让费资源, 所以需要定期去清理临时文件夹下的文件。所以最先想到了使用定时器来实现该功能。
调查: 通过查阅资料 了解到使用Java实现这个功能 有三种方法
1》使用Quartz 框架 这是一个开源的任务调度框架
2》 使用 ScheduledExecutor 实现
3》 使用 timer 实现
因为我这只是要实现一个简单定时清理临时文件夹的任务 不需要太多复杂的东西。 所以 我选择了第三种方案 自己使用jdk 自带的 timer 类来实现。
任务类 主要的业务代码
package com.sxl;
import java.util.TimerTask;
import javax.servlet.ServletContext;
/**
* 定时器
* @author sxl
*
*/
public class DelFileTask extends TimerTask{
private static boolean isRunning = false;
private ServletContext context = null;
public DelFileTask() {
super();
}
public DelFileTask(ServletContext context) {
this.context = context;
}
@Override
public void run() {
if (!isRunning) {
context.log("开始执行指定任务");
/**
* 自己的业务代码
*/
isRunning = false;
context.log("指定任务执行结束");
} else {
context.log("上一次任务执行还未结束");
}
}
}
这个类 主要是继承 TimerTask并实现它的run 方法
下面就是监听类了 监听服务器的启动并将任务添加到任务栈
package com.sxl;
import java.util.Calendar;
import java.util.Date;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class ContextListener implements ServletContextListener{
public ContextListener() {
}
private java.util.Timer timer = null;
/**
* 初始化定时器
* web 程序运行时候自动加载
*/
@Override
public void contextInitialized(ServletContextEvent arg0) {
/**
* 设置一个定时器
*/
timer = new java.util.Timer(true);
arg0.getServletContext().log("定时器已启动");
/**
* 定时器到指定的时间时,执行某个操作(如某个类,或方法)
*/
//设置执行时间
Calendar calendar =Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day =calendar.get(Calendar.DAY_OF_MONTH);//每天
//定制每天的1:00:00执行,
calendar.set(year, month, day, 01, 00, 00);
Date date = calendar.getTime();
// System.out.println(date);
int period = 24 * 60 * 60 * 1000;
//每天的date时刻执行task,每隔persion 时间重复执行
timer.schedule(new DelFileTask(arg0.getServletContext()), date, period);
// 在 指定的date时刻执行task, 仅执行一次
// timer.schedule(new DelFileTask(arg0.getServletContext()), date);
arg0.getServletContext().log("已经添加任务调度表");
}
/**
* 销毁
*/
@Override
public void contextDestroyed(ServletContextEvent arg0){
timer.cancel();
arg0.getServletContext().log("定时器销毁");
}
}
这个类 主要是设置一个调度器 并让他 按一定的要求去执行任务。
任务类 监听器类 都实现了 下一步就是在web.xml 配置监听器了
<listener>
<listener-class>com.sxl.ContextListener</listener-class>
</listener>
到了这里 一个简单的定时器基本上实现了 也能跑通了 接下来 需要做的 就是根据自己项目的实际要求 去丰富定时器类 DelFileTask 和启动定时器的ContextListener 。
java.util.Timer 类的 schedule方法说明
schedule(TimerTask task, long delay)
安排在指定延迟后执行指定的任务。 (只执行一次)
参数:
task - 所要安排的任务。
delay - 执行任务前的延迟时间,单位是毫秒。
抛出:
IllegalArgumentException - 如果 delay 是负数,或者 delay + System.currentTimeMillis() 是负数。
IllegalStateException - 如果已经安排或取消了任务,或者已经取消计时器。
schedule(TimerTask task, Date time)
安排在指定的时间执行指定的任务。如果此时间已过去,则安排立即执行该任务。 (只执行一次)
参数:
task - 所要安排的任务。
time - 执行任务的时间。
抛出:
IllegalArgumentException - 如果 time.getTime() 是负数。
IllegalStateException - 如果已经安排或取消了任务,已经取消了计时器,或者计时器线程已终止。
schedule(TimerTask task,long delay, long period)
安排指定的任务从指定的延迟后开始进行重复的固定延迟执行。以近似固定的时间间隔(由指定的周期分隔)进行后续执行。
在固定延迟执行中,根据前一次执行的实际执行时间来安排每次执行。如果由于任何原因(如垃圾回收或其他后台活动)而延迟了某次执行,则后续执行也将被延迟。从长期来看,执行的频率一般要稍慢于指定周期的倒数(假定Object.wait(long) 所依靠的系统时钟是准确的)。
固定延迟执行适用于那些需要“平稳”运行的重复活动。换句话说,它适用于在短期运行中保持频率准确要比在长期运行中更为重要的活动。这包括大多数动画任务,如以固定时间间隔闪烁的光标。这还包括为响应人类活动所执行的固定活动,如在按住键时自动重复输入字符。
参数:
task - 所要安排的任务。
delay - 执行任务前的延迟时间,单位是毫秒。
period - 执行各后续任务之间的时间间隔,单位是毫秒。
抛出:
IllegalArgumentException - 如果delay 是负数,或者 delay + System.currentTimeMillis() 是负数。
IllegalStateException - 如果已经安排或取消了任务,已经取消了计时器,或者计时器线程已终止。
schedule(TimerTask task, Date firstTime, long period)
安排指定的任务在指定的时间开始进行重复的固定延迟执行。以近似固定的时间间隔(由指定的周期分隔)进行后续执行。
在固定延迟执行中,根据前一次执行的实际执行时间来安排每次执行。如果由于任何原因(如垃圾回收或其他后台活动)而延迟了某次执行,则后续执行也将被延迟。在长期运行中,执行的频率一般要稍慢于指定周期的倒数(假定Object.wait(long) 所依靠的系统时钟是准确的)。
固定延迟执行适用于那些需要“平稳”运行的重复执行活动。换句话说,它适用于在短期运行中保持频率准确要比在长期运行中更为重要的活动。这包括大多数动画任务,如以固定时间间隔闪烁的光标。这还包括为响应人类活动所执行的固定活动,如在按住键时自动重复输入字符。
参数:
task - 所要安排的任务。
firstTime - 首次执行任务的时间。
period - 执行各后续任务之间的时间间隔,单位是毫秒。
抛出:
IllegalArgumentException - 如果time.getTime() 是负数。
IllegalStateException - 如果已经安排或取消了任务,已经取消了计时器,或者计时器线程已终止。