java.util.Timer用法须知

项目中用Timer做了定时任务,就是每天定时给某些特定的用户发送消息,可是不知道为什么,数据库中老是出现多条通知的情况,我刚开始是这样用Timer类的:

在监听器初始化中给这个Timer添加定时任务,然后就什么都不管了,结果就出现上面的情况,代码如下:

public class JobListener implements ServletContextListener {
	
	//执行任务
	private Timer timer = new Timer();
	
	public void contextInitialized(ServletContextEvent arg0) {
			Date date = new Date();
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			try {
				Date timerDate = sdf2.parse(sdf.format(new Date())+" 18:00:00");
				if(date.after(timerDate)) { //今天18点过后
					Calendar calendar = Calendar.getInstance();
					calendar.setTime(timerDate);
					calendar.add(Calendar.DATE, 1);
					timerDate = calendar.getTime();
				}
				RemindBalanceTask rbt = new RemindBalanceTask(userService, notificationService);
				timer.schedule(rbt, timerDate, (long)(24*60*60*1000));
				System.out.println("添加了一个任务");
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}
	}
	public void contextDestroyed(ServletContextEvent sce) {
		System.out.println("监听器销毁了~~~~~~~~~~~~~~~~~~~~~~~~~");
	}  

}

  

RemindBalanceTask 这个是执行代码的线程。

 

今天分析了一下可能出现了原因,分析到了项目会重启,然后监听器被再次初始化,这个时候定时任务的timer还在运行。于是就做了一个实验:

public class TestTimer extends TimerTask{

	@Override
	public void run() {
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println("我被运行了:"+dateFormat.format(new Date()));
	}

}

public class Main {
	private Timer timer = new Timer();
	
	public static void main(String[] args) {
		Main main = new Main();
		main.timer.schedule(new TestTimer(), new Date(),1000);
		System.out.println("测试");
		main.timer = null;
	}

}

  测试结果出来了,出了main方法,照样打印,也就是即使把timer指向null了这个时候计划的任务仍然在运行,于是就改变了代码:

public class Main {
	private Timer timer = new Timer();
	
	public static void main(String[] args) {
		Main main = new Main();
		main.timer.schedule(new TestTimer(), new Date(),1000);
		System.out.println("测试");
		main.timer.cancel();
	}

}

  这个时候跳出了main方法也就不打印了,哈哈,这下子项目中的问题就出现了,如果是多次重启项目而不是服务器的话,也就是监听器会被多次的重启,但是Timer始终不会消失,重启一次就多了一个Timer,这就是原因了,最后在监听器的销毁的方法中添加了this.timer.cancel();//销毁的时候把这个任务取消,否者这个任务会一直存在这句代码。每次监听器销毁的时候也把这个定时任务给取消。

posted @ 2013-04-07 12:35  andysd  阅读(586)  评论(0编辑  收藏  举报