我是靠谱客的博主 勤劳荔枝,这篇文章主要介绍web后台上的定时器Timer ,现在分享给大家,希望可以做个参考。

public class Timer
extends
Object

一种工具,线程用其安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行。

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 scheduleAtFixedRate(TimerTask task, Date firstTime, long period)
安排指定的任务在指定的时间开始进行重复的固定速率执行。
void scheduleAtFixedRate(TimerTask task, long delay, long period)
安排指定的任务在指定的延迟后开始进行重复的固定速率执行。


一、在web上配置一个定时器

1、修改web.xml文件

<listener>
<listener-class>
com.InitListener
</listener-class>
</listener>

2、添加一个Listener

package cn.edu.ccnu.listener;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
* 系统启动时的监听类 初始化系统数据
*
* @author jhoneder
*
*/
public class acitvityListener implements ServletContextListener {
public void contextDestroyed(ServletContextEvent arg0) {
// TODO Auto-generated method stub
// context销毁时,销毁初始化数据
}
public void contextInitialized(ServletContextEvent event) {
// TODO Auto-generated method stub
try {
goTimer();
} catch (Exception e) {
System.out.println("失败:" + e.getMessage());
}
}
private void goTimer() {
Timer timmerTask = new Timer();
Calendar calEnviron = Calendar.getInstance();
// 每天的01:00.am开始执行
calEnviron.set(Calendar.HOUR_OF_DAY, 1);
calEnviron.set(Calendar.MINUTE, 00);
// date为制定时间
Date dateSetter = new Date();
dateSetter = calEnviron.getTime();
// nowDate为当前时间
Date nowDateSetter = new Date();
// 所得时间差为,距现在待触发时间的间隔
long intervalEnviron = dateSetter.getTime() - nowDateSetter.getTime();
if (intervalEnviron < 0) {
calEnviron.add(Calendar.DAY_OF_MONTH, 1);
dateSetter = calEnviron.getTime();
intervalEnviron = dateSetter.getTime() - nowDateSetter.getTime();
}
// 每24小时执行一次 第一个参数定时器,第二个是第一次执行的时间 第三个是之后的循环周期
timmerTask.schedule(new activityTimer(timmerTask), intervalEnviron, 1 * 1000
* 60 * 60 * 24);
//
timmerTask.schedule(new activityTimer(timmerTask), 1000*3, 1000*6);
}
}

3、编写一个TimerTask

package cn.edu.ccnu.listener;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
/**
* 被调用执行类
*
* @author Administrator
*
*/
public class activityTimer extends TimerTask {
Timer timer = new Timer();
public activityTimer(Timer timer) {
this.timer = timer;
}
/*
* 被调用具体的方法
*/
public void run() {
System.out.println("开始执行活动状态监测!");
}
}

二、关于Timer类的分析


1、每一个Timer会启动一个线程(TimerThread),如下代码将产生5个定时器线程

import java.util.Timer;
import java.util.TimerTask;
public class TimerTestCase {
public static void main(String[] args) throws Exception {
for (int i = 0; i < 5; i++) {
Timer timer = new Timer();
timer.schedule(new MyTask(i), 10000);
}
}
}
class MyTask extends TimerTask {
private int i;
public MyTask(int i){
this.i = i;
}
@Override
public void run() {
System.out.println(i);
}
}

2、每一个Timer可以添加多个TimerTask

import java.util.Timer;
import java.util.TimerTask;
public class TimerTestCase {
public static void main(String[] args) throws Exception {
Timer timer = new Timer();
for (int i = 0; i < 5; i++) {
timer.schedule(new MyTask(i), 10000);
}
}
}
class MyTask extends TimerTask {
private int i;
public MyTask(int i){
this.i = i;
}
@Override
public void run() {
System.out.println(i);
}
}

3、TimerTask会被放入一个有优先级的队列(TimerQueue)中

import java.util.Timer;
import java.util.TimerTask;
public class TimerTestCase {
public static void main(String[] args) throws Exception {
Timer timer = new Timer();
for (int i = 0; i < 5; i++) {
timer.schedule(new MyTask(i), (10-i)*1000);
}
}
}
class MyTask extends TimerTask {
private int i;
public MyTask(int i){
this.i = i;
}
@Override
public void run() {
System.out.println(i);
}
}

4、Timer和TimerTask都是可以被取消的

5、在同一个TimerQueue中,如果前一个TimerTask没有执行完,那么下一个TimerTask是不会被执行的

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTestCase {
public static void main(String[] args) throws Exception {
Timer timer = new Timer();
for (int i = 0; i < 5; i++) {
timer.schedule(new MyTask(i), (10-i)*1000);
}
}
}
class MyTask extends TimerTask {
private int i;
public MyTask(int i){
this.i = i;
}
@Override
public void run() {
//
try {
//
Thread.sleep(i * 1000);
//
} catch (InterruptedException e) {
//
e.printStackTrace();
//
}
System.out.println(i + ":" +new Date());
}
}
输出结果

4:Sun Jan 20 22:55:17 CST 2013
3:Sun Jan 20 22:55:18 CST 2013
2:Sun Jan 20 22:55:19 CST 2013
1:Sun Jan 20 22:55:20 CST 2013
0:Sun Jan 20 22:55:21 CST 2013

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTestCase {
public static void main(String[] args) throws Exception {
Timer timer = new Timer();
for (int i = 0; i < 5; i++) {
timer.schedule(new MyTask(i), (10-i)*1000);
}
}
}
class MyTask extends TimerTask {
private int i;
public MyTask(int i){
this.i = i;
}
@Override
public void run() {
try {利用ScheduledThreadPoolExecutor定时执行任务
Thread.sleep(i * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i + ":" +new Date());
}
}

输出结果:

4:Sun Jan 20 22:57:08 CST 2013
3:Sun Jan 20 22:57:11 CST 2013
2:Sun Jan 20 22:57:13 CST 2013
1:Sun Jan 20 22:57:14 CST 2013
0:Sun Jan 20 22:57:14 CST 2013

Timer的缺陷:

  1. Timer是基于绝对时间的,因此任务的执行对系统时间变化很敏感
  2. 如果TimerTask执行时间过长,会破坏其他TimerTask的定时精确性
  3. 如果TimerTask抛出一个未受检查的异常,Timer线程并不捕获,线程将被终止,尚未执行的TimerTask将不会再执行

在Java 5.0或者更高的版本中,可以使用ScheduledThreadPoolExecutor代替Timer

三、利用ScheduledThreadPoolExecutor定时执行任务

ScheduledThreadPoolExecutor是ThreadPoolExecutor的子类;

JDK api里是这么说的:

ThreadPoolExecutor,它可另行安排在给定的延迟后运行命令,或者定期执行命令。需要多个辅助线程时,或者要求ThreadPoolExecutor 具有额外的灵活性或功能时,此类要优于 Timer

一旦启用已延迟的任务就执行它,但是有关何时启用,启用后何时执行则没有任何实时保证。按照提交的先进先出 (FIFO) 顺序来启用那些被安排在同一执行时间的任务。

public class TaskTest {
static ScheduledThreadPoolExecutor stpe = null;
static int index;
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
//构造一个ScheduledThreadPoolExecutor对象,并且设置它的容量为5个
stpe = new ScheduledThreadPoolExecutor(5);
MyTask task = new MyTask();
//隔2秒后开始执行任务,并且在上一次任务开始后隔一秒再执行一次;
//
stpe.scheduleWithFixedDelay(task, 2, 1, TimeUnit.SECONDS);
//隔6秒后执行一次,但只会执行一次。
stpe.schedule(task, 6, TimeUnit.SECONDS);
}
private static String getTimes() {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E");
Date date = new Date();
date.setTime(System.currentTimeMillis());
return format.format(date);
}
private static class MyTask implements Runnable {
@Override
public void run() {
index++;
System.out.println("2= " + getTimes()+" "
+index);
if(index >=10){
stpe.shutdown();
if(stpe.isShutdown()){
System.out.println("停止了????");
}
}
}
}
}





最后

以上就是勤劳荔枝最近收集整理的关于web后台上的定时器Timer 的全部内容,更多相关web后台上的定时器Timer内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(68)

评论列表共有 0 条评论

立即
投稿
返回
顶部