02_传统定时器回顾

传统定时器使用Timer和TimerTask组合使用

java.util.Timer:定时器,用于指定时间后任务执行一次,或者定期重复执行。

java.util.TimerTask:继承了Runnable类,本质上就是一个Runnable对象

 

Timer和TimerTask定时器主要有两种使用情景:

1)多长时间后,执行一次定时器任务

2)多长时间后,执行一次定时器任务,之后每间隔相同时间执行一次任务

 

一、定时器的使用

package com.sam;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 传统定时器回顾
 * @author SAM
 *
 */
public class TraditionalTimerTask {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Timer timer = new Timer();
		timer.scheduleAtFixedRate(new TimerTask() {
			
			@Override
			public void run() {
				System.out.println("定时器 TName=" + Thread.currentThread().getName() + ",bombing!");
			}
		}, 1000L, 3000L);
		
		// 为了观察,打印当前时间
		while (true){
			System.out.println(new Date().toLocaleString());
			try {
				Thread.sleep(1000L);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

 执行结果:

 

2017-5-13 17:23:30

定时器 TName=Timer-0,bombing!

2017-5-13 17:23:32

2017-5-13 17:23:33

2017-5-13 17:23:34

定时器 TName=Timer-0,bombing!

2017-5-13 17:23:35

2017-5-13 17:23:36

2017-5-13 17:23:37

定时器 TName=Timer-0,bombing!

2017-5-13 17:23:38

2017-5-13 17:23:39

2017-5-13 17:23:40

定时器 TName=Timer-0,bombing!

 

可以看到定时器首次1秒后执行,之后每间隔3秒都会重复执行一次定时器任务。

 

二、定时器巩固

需求:2秒后执行一次任务,接着4秒后执行一次任务,然后又回到2秒后执行一次任务,

紧接着4秒又执行一次任务,如此反复,请写出代码。

package com.sam;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 传统定时器回顾
 * 需求:2秒后执行一次任务,接着4秒后执行一次任务,然后又回到2秒后执行一次任务,
 * 紧接着4秒又执行一次任务,如此反复,请写出代码。
 * @author SAM
 *
 */
public class TraditionalTimerTask_2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// 2秒后执行定时任务
		new Timer().schedule(new MyTimerTask(), 2000L);
		
		// 为了观察,打印当前时间
		while (true){
			System.out.println(new Date().toLocaleString());
			try {
				Thread.sleep(1000L);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

class MyTimerTask extends TimerTask{

	static int count;
	@Override
	public void run() {
		// 奇数4秒,偶数2秒
		count = ++count % 2;
		System.out.println("定时器 TName=" + Thread.currentThread().getName() + ",bombing!");
		new Timer().schedule(new MyTimerTask(), 2000L + 2000L*count);
	}
}

执行结果:

 

2017-5-13 17:45:52

2017-5-13 17:45:53

定时器 TName=Timer-0,bombing!

2017-5-13 17:45:54

2017-5-13 17:45:55

2017-5-13 17:45:56

2017-5-13 17:45:57

定时器 TName=Timer-1,bombing!

2017-5-13 17:45:58

2017-5-13 17:45:59

定时器 TName=Timer-2,bombing!

2017-5-13 17:46:00

2017-5-13 17:46:01

2017-5-13 17:46:02

2017-5-13 17:46:03

定时器 TName=Timer-3,bombing!

 

接着再深入Timer类一些细节,Timer有两组启动定时器任务的方法,他们可能比较费解:

1)schedule(TimerTask task, long delay, long period) 

2)scheduleAtFixedRate(TimerTask task, long delay, long period) 

 

区别:

他们都可以实现:多长时间后,执行一次定时器任务,之后每间隔相同时间执行一次任务;

但是他们又有一些本质的区别,首先schedule是固定延期执行,而scheduleAtFixedRate是固定速率执行。

 

再具体说:

1)固定延期,根据前一次执行的实际时间来安排每一次执行。

如果由于任何原因(如垃圾回收或者其他后台活动)而延迟了某次执行,则后续执行也将延迟。

 

2)固定速率,根据已安排的初始执行时间来安排每次执行。

如果由于任何原因(如垃圾回收或者其他后台活动)而延迟了某次执行,

则将快速连续执行两次或者更多任务,从而使后续执行能够“追赶上来”。

注意这时TimerTask的执行需要考虑同步。

 

最后推荐一个开源项目,quartz,主要用来实现复杂的调度需求。

例如周一至周五早上10点定时收邮件,周六日不收邮件,

这时使用Timer和TimerTask可能比较复杂,使用quartz开源项目可以很容易的解决这类需求。

猜你喜欢

转载自wengyoulong.iteye.com/blog/2374197