Java多线程基础(二)定时器类:Timer类和TimerTask类

时间:2022-02-22 03:42:13

Java多线程基础(二)定时器类:Timer类和TimerTask类

Timer类和TimerTask类是jdk实现定时器功能的早期方法,jdk1.5以前就支持Timer类和TimerTask类。JDK1.5之后引入了新的机制,将在后续博文中研究。

1 指定时间间隔后执行任务

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

public class TraditionalTimerTest {

public static void main(String[] args) {

// 启动定时器线程,并在10000毫秒后执行TimerTask实例的run方法
new Timer().schedule(new TimerTask() {

@Override
public void run() {
System.out.println("bombing!");

}
}, 10000);

while(true) {
System.out.println("时钟时间:" + new Date().getSeconds());
try {
Thread.sleep(1000);// 主线程每隔1秒钟,打印当前时钟时间
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}

调用的主要java API的源代码及java doc:

    public void schedule(TimerTask task, long delay) {
if (delay < 0)
throw new IllegalArgumentException("Negative delay.");
sched(task, System.currentTimeMillis()+delay, 0);
}

Schedules the specified task for execution after the specified delay.
安排在指定延迟后执行指定的任务。
Parameters:
task - task to be scheduled.
delay - delay in milliseconds before task is to be executed.
Throws:
IllegalArgumentException - if delay is negative, or delay + System.currentTimeMillis() is negative.
IllegalStateException - if task was already scheduled or cancelled, timer was cancelled, or timer thread terminated.
NullPointerException - if task is null

2 指定时间间隔后循环执行任务

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

public class TraditionalTimerTest {

public static void main(String[] args) {
// 启动定时器线程,并在10000毫秒后开始,每隔3000毫秒执行一次定时任务
new Timer().schedule(new TimerTask() {// 定时任务

@Override
public void run() {
System.out.println("bombing!");

}
}, 10000, 3000);

while(true) {
System.out.println("时钟时间:" + new Date().getSeconds());
try {
Thread.sleep(1000);// 主线程每隔1秒钟,打印当前时钟时间
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}

调用的主要java API的源代码及java doc:

    public void schedule(TimerTask task, long delay, long period) {
if (delay < 0)
throw new IllegalArgumentException("Negative delay.");
if (period <= 0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, System.currentTimeMillis()+delay, -period);
}

Schedules the specified task for repeated fixed-delay execution, beginning after the specified delay. Subsequent executions take place at approximately regular intervals separated by the specified period.
安排指定的任务从指定的延迟后开始进行重复的 固定延迟执行。以近似固定的时间间隔(由指定的周期分隔)进行后续执行。

In fixed-delay execution, each execution is scheduled relative to the actual execution time of the previous execution. If an execution is delayed for any reason (such as garbage collection or other background activity), subsequent executions will be delayed as well. In the long run, the frequency of execution will generally be slightly lower than the reciprocal of the specified period (assuming the system clock underlying Object.wait(long) is accurate).
在固定延迟执行中,根据前一次执行的实际执行时间来安排每次执行。如果由于任何原因(如垃圾回收或其他后台活动)而延迟了某次执行,则后续执行也将被延迟。从长期来看,执行的频率一般要稍慢于指定周期的倒数(假定 Object.wait(long) 所依靠的系统时钟是准确的)。

Fixed-delay execution is appropriate for recurring activities that require “smoothness.” In other words, it is appropriate for activities where it is more important to keep the frequency accurate in the short run than in the long run. This includes most animation tasks, such as blinking a cursor at regular intervals. It also includes tasks wherein regular activity is performed in response to human input, such as automatically repeating a character as long as a key is held down.
固定延迟执行适用于那些需要“平稳”运行的重复活动。换句话说,它适用于在短期运行中保持频率准确要比在长期运行中更为重要的活动。这包括大多数动画任务,如以固定时间间隔闪烁的光标。这还包括为响应人机输入所执行的固定活动,如在按住键时自动重复输入字符。

Parameters:
task - task to be scheduled.
delay - delay in milliseconds before task is to be executed.
period - time in milliseconds between successive task executions.
Throws:
IllegalArgumentException - if delay < 0, or delay + System.currentTimeMillis() < 0, or period <= 0
IllegalStateException - if task was already scheduled or cancelled, timer was cancelled, or timer thread terminated.
NullPointerException - if task is null

3 更灵活地间隔

每隔2秒,4秒,2秒,4秒,…,循环执行任务。

方法1 定义一个TimerTask类

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

public class TraditionalTimerTest {

static int count = 0;

public static void main(String[] args) {

class MyTimerTask extends TimerTask {

@Override
public void run() {
count = (count+1)%2;// 用于定制不同的间隔时间
System.out.println("bombing!");
new Timer().schedule(
new MyTimerTask(),//递归地实例化新的定时任务
2000 + 2000 * count);
}
}

new Timer().schedule(new MyTimerTask(), 2000);
while(true) {
System.out.println("时钟时间:" + new Date().getSeconds());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}

方法2 定义两个/多个TimerTask类

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

public class TraditionalTimerTest {

public static void main(String[] args) {

new Timer().schedule(new MyTimerTask1(), 2000);

while(true) {
System.out.println("时钟时间:" + new Date().getSeconds());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}
class MyTimerTask1 extends TimerTask {

@Override
public void run() {
System.out.println("Task1");
new Timer().schedule(new MyTimerTask2(), 2000);// 启动定时任务2
}

}
class MyTimerTask2 extends TimerTask {

@Override
public void run() {
System.out.println("Task2");
new Timer().schedule(new MyTimerTask1(), 4000);// 启动定时任务1
}

}

4 Timer的其他常用API

返回值 方法签名
void schedule(TimerTask task, Date time)
Schedules the specified task for execution at the specified time.
安排在指定的时间执行指定的任务。如果此时间已过去,则安排立即执行该任务。
void schedule(TimerTask task, Date firstTime, long period)
Schedules the specified task for repeated fixed-delay execution, beginning at the specified time.
安排指定的任务在指定的时间开始进行重复的 固定延迟执行。以近似固定的时间间隔(由指定的周期分隔)进行后续执行。

在固定延迟执行中,根据前一次执行的实际执行时间来安排每次执行。如果由于任何原因(如垃圾回收或其他后台活动)而延迟了某次执行,则后续执行也将被延迟。在长期运行中,执行的频率一般要稍慢于指定周期的倒数(假定 Object.wait(long) 所依靠的系统时钟是准确的)。

固定延迟执行适用于那些需要“平稳”运行的重复执行活动。换句话说,它适用于在短期运行中保持频率准确要比在长期运行中更为重要的活动。这包括大多数动画任务,如以固定时间间隔闪烁的光标。这还包括为响应人类活动所执行的固定活动,如在按住键时自动重复输入字符。
void schedule(TimerTask task, long delay)
Schedules the specified task for execution after the specified delay.
安排在指定延迟后执行指定的任务。
void schedule(TimerTask task, long delay, long period)
Schedules the specified task for repeated fixed-delay execution, beginning after the specified delay.
安排指定的任务从指定的延迟后开始进行重复的 固定延迟执行。以近似固定的时间间隔(由指定的周期分隔)进行后续执行。

在固定延迟执行中,根据前一次执行的实际执行时间来安排每次执行。如果由于任何原因(如垃圾回收或其他后台活动)而延迟了某次执行,则后续执行也将被延迟。从长期来看,执行的频率一般要稍慢于指定周期的倒数(假定 Object.wait(long) 所依靠的系统时钟是准确的)。

固定延迟执行适用于那些需要“平稳”运行的重复活动。换句话说,它适用于在短期运行中保持频率准确要比在长期运行中更为重要的活动。这包括大多数动画任务,如以固定时间间隔闪烁的光标。这还包括为响应人类活动所执行的固定活动,如在按住键时自动重复输入字符。
void scheduleAtFixedRate(TimerTask task, Date firstTime, long period)
Schedules the specified task for repeated fixed-rate execution, beginning at the specified time.
安排指定的任务在指定的时间开始进行重复的 固定速率执行。以近似固定的时间间隔(由指定的周期分隔)进行后续执行。

在固定速率执行中,相对于已安排的初始执行时间来安排每次执行。如果由于任何原因(如垃圾回收或其他后台活动)而延迟了某次执行,则将快速连续地出现两次或更多次执行,从而使后续执行能够赶上来。从长远来看,执行的频率将正好是指定周期的倒数(假定 Object.wait(long) 所依靠的系统时钟是准确的)。

固定速率执行适用于那些对绝对 时间敏感的重复执行活动,如每小时准点打钟报时,或者在每天的特定时间运行已安排的维护活动。它还适用于那些完成固定次数执行的总计时间很重要的重复活动,如倒计时的计时器,每秒钟滴答一次,共 10 秒钟。最后,固定速率执行适用于安排多次重复执行的计时器任务,这些任务相互之间必须保持同步。
void scheduleAtFixedRate(TimerTask task, long delay, long period)
Schedules the specified task for repeated fixed-rate execution, beginning after the specified delay.
安排指定的任务在指定的延迟后开始进行重复的 固定速率执行。以近似固定的时间间隔(由指定的周期分隔)进行后续执行。

在固定速率执行中,根据已安排的初始执行时间来安排每次执行。如果由于任何原因(如垃圾回收或其他后台活动)而延迟了某次执行,则将快速连续地出现两次或更多的执行,从而使后续执行能够“追赶上来”。从长远来看,执行的频率将正好是指定周期的倒数(假定 Object.wait(long) 所依靠的系统时钟是准确的)。

固定速率执行适用于那些对绝对 时间敏感的重复执行活动,如每小时准点打钟报时,或者在每天的特定时间运行已安排的维护活动。它还适用于那些完成固定次数执行的总计时间很重要的重复活动,如倒计时的计时器,每秒钟滴答一次,共 10 秒钟。最后,固定速率执行适用于安排多个重复执行的计时器任务,这些任务相互之间必须保持同步。

更多详细API信息可以参考Java SE API:
英文API:http://docs.oracle.com/javase/6/docs/api/index.html
中文API:http://tool.oschina.net/apidocs/apidoc?api=jdk-zh

更复杂的定时器可以使用quartz库:http://www.quartz-scheduler.org/