2010-05-27 60 views
1

我有一個計時器線程,需要在一天的特定時刻運行以執行數據庫的增量複製。現在它的運行時間爲每小時15分鐘,每小時30分鐘和每小時45分鐘。這是代碼我有一個好的工作:如何使運行在x:00 x:15 x:30和x:45的線程在2:00執行不同的操作

public class TimerRunner implements Runnable { 

    private static final Semaphore lock = new Semaphore(1); 

    private static final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); 

    public static void initialize() { 
     long delay = getDelay(); 
     executor.schedule(new TimerRunner(), delay, TimeUnit.SECONDS); 
    } 

    public static void destroy() { 
     executor.shutdownNow(); 
    } 

    private static long getDelay() { 
     Calendar now = Calendar.getInstance(); 
     long p = 15 * 60; // run at 00, 15, 30 and 45 minutes past the hour 
     long second = now.get(Calendar.MINUTE) * 60 + now.get(Calendar.SECOND); 
     return p - (second % p); 
    } 

    public static void replicate() { 
     if (lock.tryAcquire()) { 
      try { 
       Thread t = new Thread(new Runnable() { 
        public void run() { 
         try { 
          // here is where the magic happens 
         } finally { 
          lock.release(); 
         } 
        } 
       }); 
       t.start(); 
      } catch (Exception e) { 
       lock.release(); 
      } 
     } else { 
      throw new IllegalStateException("already running a replicator"); 
     } 
    } 

    public void run() { 
     try { 
      TimerRunner.replicate(); 
     } finally { 
      long delay = getDelay(); 
      executor.schedule(new TimerRunner(), delay, TimeUnit.SECONDS); 
     } 
    } 

} 

這個過程是通過調用TimerRunner.initialize()當服務器啓動並調用TimerRunner.destroy()開始。

我已經創建了一個完整的複製過程(而不是增量式),我想在一天中的某個時刻運行,比如凌晨2點。如何改變上面的代碼來做到這一點?我認爲它應該非常簡單,就好像現在是凌晨2點左右一樣,而且我已經完成了完整的複製並且現在已經完成了很長一段時間,但是我無法獲得該權利。

請注意,有時複製過程需要更長的時間才能完成。有時超過15分鐘,在凌晨2點左右運行時出現問題。

回答

5

恕我直言,如果它做了不同的事情,它不應該是相同的可運行的。創建一些通用的抽象類和兩個子類,每個都有特定的行爲。然後讓您的日程安排邏輯在適當的時間安排合適的線程。

否則,你有一個對象有兩個職責,需要知道有關調度。我個人也會從當前的getDelay()中獲取調度邏輯,並進入一些複製調度管理器對象,該對象也將保持狀態(例如,最近執行的內容)。

最後,您可能希望爲您的調度程序使用庫的東西,它感覺對我來說就像是在重新創造一些車輪。

3

不要建立自己的調度程序,使用現有的調度程序。

如果您希望在Java中使用quartz並針對在不同計劃上運行的增量備份和完整備份安排2個單獨的任務。

但在你的情況下,一個簡單的cron腳本可能會很好。如果您在Windows上運行,請在Windows幫助文件中搜索Scheduled Tasks

編輯
下面是避免同時運行完全和增量,同時在crontab:在你shell腳本設置你的java環境和運行負責任務的Java程序

*/15 0,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23 * * * /path/to/run-incremental-backup.sh 
15,30,45 1 * * * /path/to/run-incremental-backup.sh 
0 1 * * * /path/to/run-full-backup.sh 

Quartz時間表可以很好地調整,其中一個標準調度程序完全模仿crontab。我將這作爲練習給讀者。

順便說一句,我已經安排完整備份在凌晨1點運行,請參閱下面的原因。

註記夏令時
我不知道世界上你在哪裏,如果你是少數幸運兒,你沒有夏令時的一個,否則你的本地時間檢查地區當局。北美標準時間爲凌晨2:00,夏令時爲凌晨3:00,所以如果您的完整備份時間爲凌晨2:00,那麼每年的一天(S到D),您的完整備份將會在沒有跑,而另一天(D到S)它會跑兩次。

+0

這兩個調度程序的一個問題是,在凌晨2點,我將不得不運行增量和完整的,但我只需要全部。如何檢查兩個預定過程之間的競賽狀況? – rmarimon 2010-05-27 21:37:47

+0

@rmarimon。我已更新我的答案以解決您的意見。 – 2010-05-28 11:29:24