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("停止了????");
                }
            }
        }
    }
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值