寫完了基礎篇,想了非常久要不要去寫進階篇。去寫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[n] 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類的原理非常easy,能夠使用的函數不多。以下將所有列出。
(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 結束!");
}
}
