JAVA技巧(JOTM中定時(shí)器的源碼分析)

字號(hào):

在Jotm中看到一個(gè)很齊全的定時(shí)器,貼出來(lái)以防備用;
    package org.objectweb.jotm;
    import java.util.Vector;
    /**
    *
    *對(duì)計(jì)時(shí)器列表中的計(jì)時(shí)器進(jìn)行倒計(jì)時(shí)
    */
    class Clock extends Thread {
    private TimerManager tmgr;
    public Clock(TimerManager tmgr) {
    super("JotmClock");
    if (TraceTm.jta.isDebugEnabled()) {
    TraceTm.jta.debug("Clock constructor");
    }
    this.tmgr = tmgr;
    }
    public void run() {
    tmgr.clock();
    }
    }
    /**
    *
    *Examda提示:出去計(jì)時(shí)器列表中的過(guò)期計(jì)時(shí)器,如倒計(jì)時(shí)為負(fù)數(shù)
    */
    class Batch extends Thread {
    private TimerManager tmgr;
    public Batch(TimerManager tmgr) {
    super("JotmBatch");
    if (TraceTm.jta.isDebugEnabled()) {
    TraceTm.jta.debug("Batch constructor");
    }
    this.tmgr = tmgr;
    }
    public void run() {
    tmgr.batch();
    }
    }
    /**
    *含有兩個(gè)計(jì)時(shí)器列表,并且含有兩個(gè)線程,一個(gè)線程進(jìn)行計(jì)時(shí)器的倒計(jì)時(shí),
    *一個(gè)線程移除過(guò)期計(jì)時(shí)器并且執(zhí)行計(jì)時(shí)器的監(jiān)聽器動(dòng)作;
    */
    public class TimerManager {
    // threads managing the service.
    private static Batch batchThread;
    private static Clock clockThread;
    // lists
    //計(jì)時(shí)器列表
    private Vector timerList = new Vector();
    //過(guò)期計(jì)時(shí)器列表
    private Vector expiredList = new Vector();
    //單例
    private static TimerManager unique = null;
    private static boolean shuttingdown = false;
    /**
    * Constructor
    */
    private TimerManager() {
    // launch threads for timers
    batchThread = new Batch(this);
    batchThread.setDaemon(true);
    batchThread.start();
    clockThread = new Clock(this);
    clockThread.setDaemon(true);
    clockThread.start();
    }
    /**
    * 這個(gè)時(shí)間管理器是一個(gè)單例類;
    */
    public static TimerManager getInstance() {
    if (unique == null)
    unique = new TimerManager();
    return unique;
    }
    //停止時(shí)間管理器中的計(jì)時(shí)器;
    public static void stop(boolean force) {
    if (TraceTm.jta.isDebugEnabled()) {
    TraceTm.jta.debug("Stop TimerManager");
    }
    TimerManager tmgr = getInstance();
    shuttingdown = true;
    while (clockThread.isAlive() || batchThread.isAlive()) {
    try {
    Thread.sleep(100);
    } catch (InterruptedException e) {
    break;
    }
    }
    if (TraceTm.jta.isDebugEnabled()) {
    TraceTm.jta.debug("TimerManager has stopped");
    }
    }
    public static void stop() {
    stop(true);
    }
    /**
    * cney speed up the clock x1000 when shutting down
    * update all timers in the list
    * each timer expired is put in a special list of expired timers
    * they will be processed then by the Batch Thread.
    */  public void clock() {
    //無(wú)限循環(huán)
    while (true) {
    try {
    //線程休息一秒
    Thread.sleep(shuttingdown?1:1000); // 1 second or 1ms shen shuttingdown
    // Thread.currentThread().sleep(shuttingdown?1:1000); // 1 second or 1ms shen shuttingdown
    synchronized(timerList) {
    int found = 0;
    boolean empty = true;
    for (int i = 0; i < timerList.size(); i++) {
    TimerEvent t = (TimerEvent) timerList.elementAt(i);
    //如果沒有活動(dòng)的計(jì)時(shí)器,那么計(jì)時(shí)器隊(duì)列為空;
    if (!t.isStopped()) {
    empty = false;
    }
    //如果計(jì)時(shí)器過(guò)期
    if (t.update() <= 0) {
    //從計(jì)時(shí)器隊(duì)列中移除
    timerList.removeElementAt(i--);
    if (t.valid()) {
    //該計(jì)時(shí)器存在計(jì)時(shí)器監(jiān)聽器的話,把這個(gè)計(jì)時(shí)器加入過(guò)期計(jì)時(shí)器
    //如果不存在,則廢除,哪個(gè)隊(duì)列都不加入
    expiredList.addElement(t);
    found++;
    //如果持續(xù)的話,則繼續(xù)把該計(jì)時(shí)器再次加入計(jì)時(shí)器隊(duì)列中
    if (t.ispermanent() && !shuttingdown) {
    t.restart();
    timerList.addElement(t);
    }
    }
    }
    // Be sure there is no more ref on bean in this local variable.
    t = null;
    }
    if (found > 0) {
    //喚醒線程;
    timerList.notify();
    } else {
    if (empty && shuttingdown) {
    break;
    }
    }
    }
    } catch (InterruptedException e) {
    TraceTm.jta.error("Timer interrupted");
    }
    }
    synchronized(timerList) { // notify batch so that function can return.
    timerList.notify();
    }
    }
    /**
    * process all expired timers
    */
    public void batch() {
    while (!(shuttingdown && timerList.isEmpty() && expiredList.isEmpty())) {
    TimerEvent t;
    synchronized(timerList) {
    while (expiredList.isEmpty()) {
    if (shuttingdown) return;
    try {
    //計(jì)時(shí)器計(jì)時(shí)線程讓如果找到到期的計(jì)時(shí)器,那么就會(huì)喚醒執(zhí)行該計(jì)時(shí)器的線程執(zhí)行監(jiān)聽器動(dòng)作
    timerList.wait();
    } catch (Exception e) {
    TraceTm.jta.error("Exception in Batch: ", e);
    }
    }
    t = (TimerEvent) expiredList.elementAt(0);
    expiredList.removeElementAt(0);
    }
    //執(zhí)行動(dòng)作;
    t.process();
    }
    }
    /**
    * add a new timer in the list
    * @param tel Object that will be notified when the timer expire.
    * @param timeout nb of seconds before the timer expires.
    * @param arg info passed with the timer
    * @param permanent true if the timer is permanent.
    */
    public TimerEvent addTimer(TimerEventListener tel, long timeout, Object arg, boolean permanent) {
    TimerEvent te = new TimerEvent(tel, timeout, arg, permanent);
    synchronized(timerList) {
    timerList.addElement(te);
    }
    return te;
    }
    /**
    * remove a timer from the list. this is not very efficient.
    * A better way to do this is TimerEvent.unset()
    * @deprecated
    */
    public void removeTimer(TimerEvent te) {
    synchronized(timerList) {
    timerList.removeElement(te);
    }
    }
    }