您的位置:首页 > 编程语言 > Java开发

JAVA随笔篇一(Timer源码分析和scheduleAtFixedRate的使用)

2015-08-11 14:51 507 查看
写完了基础篇,想了很久要不要去写进阶篇,去写JSP等等的使用方法,最后决定先不去写,因为自己并不是JAVA方面的大牛,目前也在边做边学,所以决定先将自己不懂的拿出来学并记下来。

Timer是Java自带的java.util.Timer类,通过调度一个java.util.TimerTask任务。这种方式可以让程序按照某一个频度执行。

1、Timer类的源码分析:

public class Timer {
/**
* The timer task queue.  This data structure is shared with the timer
* thread.  The timer produces tasks, via its various schedule calls,
* and the timer thread consumes, executing timer tasks as appropriate,
* and removing them from the queue when they're obsolete.
*/
private TaskQueue queue = new TaskQueue();

/**
* The timer thread.
*/
private TimerThread thread = new TimerThread(queue);
首先Timer类定义了两个私有变量TaskQueue和TimerThread。

TaskQueue:Timer类定义了一个定时器任务队列,一个TimerTasks的优先级队列。

class TaskQueue {
/**
* Priority queue represented as a balanced binary heap: the two children
* of queue
are queue[2*n] and queue[2*n+1]. The priority queue is
* ordered on the nextExecutionTime field: The TimerTask with the lowest
* nextExecutionTime is in queue[1] (assuming the queue is nonempty). For
* each node n in the heap, and each descendant of n, d,
* n.nextExecutionTime <= d.nextExecutionTime.
*/
private TimerTask[] queue = new TimerTask[128];
TimerThread:Timer类的任务执行线程,从Thread类继承。以TaskQueue为参数。

在使用Timer类,首先new一个Timer对象,然后利用scheduleXXX函数执行任务,首先分析Timer对象构造过程:

   public Timer() {
        this("Timer-" + serialNumber());
    }
public Timer(boolean isDaemon) {
        this("Timer-" + serialNumber(), isDaemon);
    }<span style="white-space:pre">	</span>
public Timer(String name) {
thread.setName(name);
thread.start();
}
public Timer(String name, boolean isDaemon) {
thread.setName(name);
thread.setDaemon(isDaemon);
thread.start();
}
可以看出,Timer在构造对象过程中,需要启动一个TimerThread线程,因此可以猜测,TimerThread线程和Timer对象共同维护一个TaskQueue,利用TaskQueue进行信息传递。
接下来看scheduleXXX函数,所有的scheduleXXX函数都需要调用sched方法,

private void sched(TimerTask task, long time, long period) {
if (time < 0)
throw new IllegalArgumentException("Illegal execution time.");

synchronized(queue) {
if (!thread.newTasksMayBeScheduled)
throw new IllegalStateException("Timer already cancelled.");

synchronized(task.lock) {
if (task.state != TimerTask.VIRGIN)
throw new IllegalStateException(
"Task already scheduled or cancelled");
task.nextExecutionTime = time;
task.period = period;
task.state = TimerTask.SCHEDULED;
}

queue.add(task);
if (queue.getMin() == task)
queue.notify();
}
}这里首先介绍一下TimerTask类:
public abstract class TimerTask implements Runnable {
/**
* This object is used to control access to the TimerTask internals.
*/
final Object lock = new Object();

TimerTask类实现了Runnable接口,待执行的任务置于run()中。在构造定时任务的时候,从TimerTask继承并实现run方法。并创建任务传给scheduleXXX方法。
从sched方法中可以看出,sched方法中需要操作TaskQueue队列,而TimerThread线程启动之后同样使用这个队列,这就必须使用synchronized保证多线程安全使用。

2、scheduleXXX的使用:

Timer类的原理很简单,可以使用的函数不多,下面将全部列出。

(1)void java.util.Timer.schedule(TimerTask task, long delay):多长时间(毫秒)后执行任务

(2)void java.util.Timer.schedule(TimerTask task, Date time):设定某个时间执行任务

(3)void java.util.Timer.schedule(TimerTask task, long delay, long period):delay时间后开始执行任务,并每隔period时间调用任务一次。

(4)void java.util.Timer.schedule(TimerTask task, Date firstTime, long period):第一次在指定firstTime时间点执行任务,之后每隔period时间调用任务一次。

(5)void java.util.Timer.scheduleAtFixedRate(TimerTask task, long delay, long period):delay时间后开始执行任务,并每隔period时间调用任务一次。

(6)void java.util.Timer.scheduleAtFixedRate(TimerTask task, Date firstTime, long period):第一次在指定firstTime时间点执行任务,之后每隔period时间调用任务一次。

(7)void java.util.Timer.cancel():终止该Timer

(8)boolean java.util.TimerTask.cancel():终止该TimerTask

这些scheduleXXX方法中,除了(1)(2)外,其他都可以重复调用任务,主要的区别就是schedule和scheduleAtFixedRate的差别。

schedule()方法更注重保持间隔时间的稳定:保障每隔period时间可调用一次。



scheduleAtFixedRate()方法更注重保持执行频率的稳定:保障多次调用的频率趋近于period时间,如果某一次调用时间大于period,下一次就会尽量小于period,以保障频率接近于period


3、Timer类的使用示列

首先创建一个任务:

<pre name="code" class="java">import java.util.TimerTask;
public class MyTask extends TimerTask{
private int id;
public MyTask(int id){
this.id = id;
}
public void run(){
System.out.println("线程" + id + ":正在执行");
//System.gc();
}
}

main函数代码:

import java.util.Date;
import java.util.Timer;
public class Test{
public static void main(String[] args){
Timer timer = new Timer();
timer.schedule(new MyTask(1), 5000);// 5秒后启动任务
MyTask secondTask = new MyTask(2);
timer.schedule(secondTask, 1000, 3000);
// 1秒后启动任务,以后每隔3秒执行一次线程
Date date = new Date();
timer.schedule(new MyTask(3), new Date(date.getTime() + 1000));
// 以date为参数,指定某个时间点执行线程
// timer.cancel();
// secondTask.cancel();
System.out.println("main thread 结束!");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息