熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> JSP教程 >> 正文

Java語言中Timer類的簡潔用法(二)

2022-06-13   來源: JSP教程 

  實現計劃框架
  在上一節我們學習了如何使用計劃框架並將它與 Java 定時器框架進行了比較下面我將向您展示如何實現這個框架除了 清單 中展示的 ScheduleIterator 接口構成這個框架的還有另外兩個類 —— Scheduler 和 SchedulerTask 這些類實際上在內部使用 Timer 和 SchedulerTask因為計劃其實就是一系列的單次定時器
  
  清單 顯示了這兩個類的源代碼
  
  清單 Scheduler
  
  package orgtilingscheduling;
  
  import javautilDate;
  import javautilTimer;
  import javautilTimerTask;
  
  public class Scheduler {
  
    class SchedulerTimerTask extends TimerTask {
      private SchedulerTask schedulerTask;
      private ScheduleIterator iterator;
      public SchedulerTimerTask(SchedulerTask schedulerTask
          ScheduleIterator iterator) {
        thisschedulerTask = schedulerTask;
        erator = iterator;
      }
      public void run() {
        schedulerTaskrun();
        reschedule(schedulerTask iterator);
      }
    }
  
    private final Timer timer = new Timer();
  
    public Scheduler() {
    }
  
    public void cancel() {
      timercancel();
    }
  
    public void schedule(SchedulerTask schedulerTask
        ScheduleIterator iterator) {
  
      Date time = iteratornext();
      if (time == null) {
        schedulerTaskcancel();
      } else {
        synchronized(schedulerTasklock) {
          if (schedulerTaskstate != SchedulerTaskVIRGIN) {
           throw new IllegalStateException(Task already
           scheduled + or cancelled);
          }
          schedulerTaskstate = SchedulerTaskSCHEDULED;
          schedulerTasktimerTask =
            new SchedulerTimerTask(schedulerTask iterator);
          timerschedule(schedulerTasktimerTask time);
        }
      }
    }
  
    private void reschedule(SchedulerTask schedulerTask
        ScheduleIterator iterator) {
  
      Date time = iteratornext();
      if (time == null) {
        schedulerTaskcancel();
      } else {
        synchronized(schedulerTasklock) {
          if (schedulerTaskstate != SchedulerTaskCANCELLED) {
            schedulerTasktimerTask =
              new SchedulerTimerTask(schedulerTask iterator);
            timerschedule(schedulerTasktimerTask time);
          }
        }
      }
    }
  
  }
  
  清單 顯示了 SchedulerTask 類的源代碼
  
  package orgtilingscheduling;
  
  import javautilTimerTask;
  
  public abstract class SchedulerTask implements Runnable {
  
    final Object lock = new Object();
  
    int state = VIRGIN;
    static final int VIRGIN = ;
    static final int SCHEDULED = ;
    static final int CANCELLED = ;
  
    TimerTask timerTask;
  
    protected SchedulerTask() {
    }
  
    public abstract void run();
  
    public boolean cancel() {
      synchronized(lock) {
        if (timerTask != null) {
          timerTaskcancel();
        }
        boolean result = (state == SCHEDULED);
        state = CANCELLED;
        return result;
      }
    }
  
    public long scheduledExecutionTime() {
      synchronized(lock) {
       return timerTask == null ? : timerTaskscheduledExecutionTime();
      }
    }
  
  }
   就像煮蛋計時器Scheduler 的每一個實例都擁有 Timer 的一個實例用於提供底層計劃Scheduler 並沒有像實現煮蛋計時器時那樣使用一個單次定時器它將一組單次定時器串接在一起以便在由 ScheduleIterator 指定的各個時間執行 SchedulerTask 類
  
  考慮 Scheduler 上的 public schedule() 方法 —— 這是計劃的入口點因為它是客戶調用的方法(在 取消任務 一節中將描述僅有的另一個 public 方法 cancel())通過調用 ScheduleIterator 接口的 next()發現第一次執行 SchedulerTask 的時間然後通過調用底層 Timer 類的單次 schedule() 方法啟動計劃在這一時刻執行為單次執行提供的 TimerTask 對象是嵌入的 SchedulerTimerTask 類的一個實例它包裝了任務和迭代器(iterator)在指定的時間調用嵌入類的 run() 方法它使用包裝的任務和迭代器引用以便重新計劃任務的下一次執行reschedule() 方法與 schedule() 方法非常相似只不過它是 private 的並且執行一組稍有不同的 SchedulerTask 狀態檢查重新計劃過程反復重復為每次計劃執行構造一個新的嵌入類實例直到任務或者調度程序被取消(或者 JVM 關閉)
  
  類似於 TimerTaskSchedulerTask 在其生命周期中要經歷一系列的狀態創建後它處於 VIRGIN 狀態這表明它從沒有計劃過計劃以後它就變為 SCHEDULED 狀態再用下面描述的方法之一取消任務後它就變為 CANCELLED 狀態管理正確的狀態轉變 —— 如保證不對一個非 VIRGIN 狀態的任務進行兩次計劃 —— 增加了 Scheduler 和 SchedulerTask 類的復雜性在進行可能改變任務狀態的操作時代碼必須同步任務的鎖對象
  
  取消任務
  取消計劃任務有三種方式第一種是調用 SchedulerTask 的 cancel() 方法這很像調用 TimerTask 的 cancel()方法任務再也不會運行了不過已經運行的任務仍會運行完成 cancel() 方法的返回值是一個布爾值表示如果沒有調用 cancel() 的話計劃的任務是否還會運行更准確地說如果任務在調用 cancel() 之前是 SCHEDULED 狀態那麼它就返回 true如果試圖再次計劃一個取消的(甚至是已計劃的)任務那麼 Scheduler 就會拋出一個 IllegalStateException
  
  取消計劃任務的第二種方式是讓 ScheduleIterator 返回 null這只是第一種方式的簡化操作因為 Scheduler 類調用 SchedulerTask 類的 cancel()方法如果您想用迭代器而不是任務來控制計劃停止時間時就用得上這種取消任務的方式了
  
  第三種方式是通過調用其 cancel() 方法取消整個 Scheduler這會取消調試程序的所有任務並使它不能再計劃任何任務
  
  擴展 cron 實用程序
  可以將計劃框架比作 UNIX 的 cron 實用程序只不過計劃次數的規定是強制性而不是聲明性的例如在 AlarmClock 實現中使用的 DailyIterator 類它的計劃與 cron 作業的計劃相同都是由以 * * * 開始的 crontab 項指定的(這些字段分別指定分鐘小時月和星期)
  
  不過計劃框架比 cron 更靈活想像一個在早晨打開熱水的 HeatingController 應用程序我想指示它在每個工作日上午 : 打開熱水在周未上午 : 打開熱水使用 cron我需要兩個 crontab 項( * * * * 而使用 ScheduleIterator 的解決方案更簡潔一些因為我可以使用復合(composition)來定義單一迭代器清單 顯示了其中的一種方法
  
  清單 用復合定義單一迭代器
  
  int[] weekdays = new int[] {
      CalendarMONDAY
      CalendarTUESDAY
      CalendarWEDNESDAY
      CalendarTHURSDAY
      CalendarFRIDAY
    };
    int[] weekend = new int[] {
      CalendarSATURDAY
      CalendarSUNDAY
    };
    ScheduleIterator i = new CompositeIterator(
      new ScheduleIterator[] {
        new RestrictedDailyIterator( weekdays)
        new RestrictedDailyIterator( weekend)
      }
    );
  RestrictedDailyIterator 類很像 DailyIterator只不過它限制為只在一周的特定日子裡運行而一個 CompositeIterator 類取得一組 ScheduleIterators並將日期正確排列到單個計劃中
  
  有許多計劃是 cron 無法生成的但是 ScheduleIterator 實現卻可以例如每個月的最後一天描述的計劃可以用標准 Java 日歷算法來實現(用 Calendar 類)
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19382.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.