定时器线程

来源:互联网 发布:人民网微博微信矩阵 编辑:程序博客网 时间:2024/05/16 05:27
  定时器线程
有时候需要每隔一段时间去执行某个任务。Java 中有两个特殊的类,用来实现定时任务调度:
java.util.Timer 和 java.util.TimerTask。
Timer 类是 Java 中一种线程设施,用于安排以后在后台线程中执行的任务,可以调度任务执行一次
或定期重复执行。与每个 Timer 对象对应的是单个后台线程,用于顺序的执行所有计时器任务。
TimerTask 类实现上是一个线程类,其定义如下:
public abstract class TimerTask
extends Object
implements Runnable
通常扩展 TimerTask 以创建自己的定时任务,然后使用 Timer 定义时调度该任务的执行。 也就是说,
Timer 负责计时,具体的任务由 TimerTask 来完成。
21.1.1  定时执行一个异步任务
在下面的例子中,5 秒种以后在控制台打印输出一句话。
首先,要创建一个待执行的任务,这是 TimerTask 的子类:
import java.awt.Toolkit;
import java.util.TimerTask;
public class MyTimerTask extends TimerTask{
private Timer timer;
public MyTimerTask(Timer timer) {
this.timer = timer;
}
@Override
public void run() {
System.out.println("任务执行");
timer.cancel();        //终止定时器
//         System.exit(0);    //退出程序
}
}
然后通过 Timer 来调度该任务的执行。代码如下:
import java.util.Timer;
public class TimerDemo {
2
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new MyTimerTask(timer), 5000);     //5 秒后执行指定任务一次
}
}
编译并执行上述程序,会发现程序运行 5 秒钟后,会在控制台上打印出"任务执行"这句话。
21.1.2   原理
其基本处理模型是单线程调度的任务队列模型,Timer 不停地接受调度任务,所有任务接受 Timer
调度后加入 TaskQueue,TimerThread 不停地去 TaskQueue 中取任务来执行.
从图上不难看出,这就是生产者--消费者模型的一种特例:多生产者-单消费者模型。
此种方式的不足之处为当某个任务执行时间较长,以致于超过了 TaskQueue 中下一个任务开始执行
的时间,会影响整个任务执行的实时性。为了提高实时性,可以采用多个消费者一起消费来提高处理效
率,避免此类问题的实现。
21.1.3   周期性地执行一个异步任务
如果想要周期性地执行一个异步任务,那么可以在调度任务时,在 schedule()方法中指定任务开始
的时间和执行周期。
修改前面的 MyTimerTask.java 代码如下:
import java.awt.Toolkit;
import java.util.TimerTask;
public class MyTimerTask extends TimerTask{
@Override
public void run() {
Toolkit.getDefaultToolkit().beep();  //发出响声 
·3·
}
}
修改前面的 TimerDemo.java 代码如下:
import java.util.Timer;
public class TimerDemo {
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new MyTimerTask(timer), 5000, 1*1000);    //5 秒钟后开始执行任务,每隔一秒执行一次
}
}
编译并运行上述程序,会发现每隔一秒钟就发出“滴”的一声。
21.1.4   在指定的时间执行任务
还可以指定某个任务在指定的时间才执行。请看下面的代码:
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
public class TimerDemo {
public static void main(String[] args) {
Timer timer = new Timer();
//指定任务在 23:01:00 执行
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 1);
calendar.set(Calendar.SECOND, 0);
Date time = calendar.getTime();
timer = new Timer();
timer.schedule(new MyTimerTask(), time);
}
}
在上面的代码中,指定在晚上 23:01:00 执行指定的任务。
21.1.5   示例:微波炉定时器
下面的程序模拟一个微波炉定时加热功能。
/*
*  微波炉计时器
*/
package com.derun.timer.example; 
4
import java.awt.Toolkit;
import java.util.Timer;
import java.util.TimerTask;
public class MicrowaveTimer {
private final Timer timer = new Timer();
private final int minutes;
public MicrowaveTimer(int minutes) {
this.minutes = minutes;
}
public void start() {
//要执行的任务
Microwave heating = new Microwave(timer);
//将任务和计时器关联在一起。第一个参数是要执行的任务
//第二个参数是执行任务前的延迟时间,单位是毫秒
timer.schedule(heating, minutes * 60 * 1000);
}
public static void main(String[] args) {
final int minutes = 1;
System.out.println("微波炉加热计时器开始记时," + minutes + "分钟后食物加热后会播放声音!");
MicrowaveTimer microwaveTimer = new MicrowaveTimer(minutes);
microwaveTimer.start();
}
//微波炉加热任务
class Microwave extends TimerTask {
Timer timer;
Microwave(Timer timer) {
this.timer = timer;
}
@Override
public void run() {
playSound();       //加热时间到,播放声音
timer.cancel();    //结束进程
}
private void playSound() {
System.out.println("食物加热好了,播放声音!~~~");
Toolkit.getDefaultToolkit().beep(); //"叮"
}

·5·
}
21.1.6   终止定时器
默认情况下,只要一个程序的 timer 线程在运行,那么这个程序就会保持运行。当然,可以通过以
下四种方法终止一个 timer 线程:
1)  调用 timer 的 cancle 方法。可以从程序的任何地方调用此方法,甚至在一个 timer task 的 run 方
法里。
2)  让 timer 线程成为一个 daemon 线程(可以在创建 timer 时使用 new Timer(true)达到这个目地),
这样当程序只有 daemon 线程的时候,它就会自动终止运行。
3)  当 timer 相关的所有 task 执行完毕以后,删除所有此 timer 对象的引用(置成 null),这样 timer
线程也会终止。
4)  调用 System.exit 方法,使整个程序(所有线程)终止。
0 0
原创粉丝点击