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);
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 結束!"); } }
JAVA隨筆篇一(Timer源代碼分析和scheduleAtFixedRate的使用)