標籤:java 定時器 timer類 scheduleatfixedrate
寫完了基礎篇,想了很久要不要去寫進階篇,去寫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類的原理很簡單,可以使用的函數不多,下面將全部列出。
(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 結束!"); }}
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
JAVA隨筆篇一(Timer源碼分析和scheduleAtFixedRate的使用)