2014-05-23 19 views
0

我需要替換接受時間源的java.util.Timer或java.util.concurrent.ScheduledExecutorService,以便它可以從系統時間驅動出其他一些參考。我使用這個定時器來定期執行一個方法,但是當應用程序處於「實時」模式時需要系統時間來驅動這個時間段,而當應用程序處於「回放」模式時需要這個時間段。Java - 接受時間源的Timer類

我確實看到有一些第三方庫,如番石榴秒錶,其功能類似於我所要求的功能,但由於我正在使用的信息系統的策略,我更喜歡Java本地的某些東西。

我可能最終不得不寫自己的,但我在這裏問這裏,因爲這似乎是許多人會有的需要......或者當處理具有時間流逝的替代概念的應用程序或測試嵌入單元計時器。

回答

0

如果有人需要它,這裏是我最終解決的解決方案。

public interface TimeSource { 
    long currentTimeMillis(); 
} 

public class AlternateTimeSource implements TimeSource { 

    long currentTime = 0;  

    public AlternateTimeSource() { 
    } 

    public setTime(long time) { 
     if (time > currentTime) currentTime = time; 
    } 

    @Override 
    public long currentTimeMillis() { 
     return currentTime; 
    } 
} 

public class SystemTimeSource implements TimeSource { 

    @Override 
    public long currentTimeMillis() { 
     return System.currentTimeMillis(); 
    } 
} 

class SourcedTimerThread extends Thread { 

    TimeSource reference_; 
    TimerTask task_; 
    long period_; 
    long executionTime_; 
    boolean done = false; 

    SourcedTimerThread(TimeSource reference,TimerTask task,long delay,long period) { 
     reference_  = reference; 
     task_   = task; 
     period_  = period >= 0 ? period : 0; 
     executionTime_ = reference_.currentTimeMillis() + (delay >= 0 ? delay : 0); 
     setName("SourcedTimerThread_"+reference_.getClass().getSimpleName()); 
     start(); 
    } 

    public void cancel() { 
     done = true; 
     interrupt(); 
    } 

    public void run() { 

     long currentTime; 

     while (!done) { 
      try { 
       currentTime = reference_.currentTimeMillis(); 
       if (executionTime_>currentTime) { 
        // Task hasn't yet fired; wait 
        sleep(1);     } 
       else { 
        task_.run(); 
        if (period_ > 0) { 
         // Repeating task, reschedule 
         executionTime_ = ((period_ < 0) ? currentTime-period_ : executionTime_ + period_); 
        } 
        else { 
         // Non-repeating task, done 
         break; 
        } 
       } 
      } catch (InterruptedException e) { 
      } 
     } 
    } 
} 

用法:

// Build source 
TimeSource source = null; 
if (alternate) { 
    source = new AlternateTimeSource(); 
} 
else { 
    source = new SystemTimeSource(); 
} 

// Configure timer 
SourcedTimerThread t = new SourcedTimerThread(source,new TimerTask() { 
    @Override 
    void run() { 
     System.out.println("Yay!"); 
    } 
}, delayMs, periodMs); 

// Drive timer if necessary 
if (alternate) { 
    // Drive timer based on alternate source such as data 
    source.setTime(dataRecord.getTime()); 
} 

// When ready to cleanup 
t.cancel(); 
2

您可以實現java.util.concurrent.ScheduledExecutorService使用自定義的時間源,通過執行以下操作:

計算偏移或自定義時間源和系統時間(初始化)間的增量,並保持到三角洲你的執行ScheduledExecutorService。當調用schedule(以及接口中的類似方法)時,請使用您在初始化時計算出的相同偏移量,並在提供的TimeUnits上應用這些偏移量。那樣 - 你可以依靠調度器的現有實現。

+0

感謝您的響應。我認爲這種方法可以改變時間,但我可能需要處理非線性時間流逝......例如:1秒的實時傳球:3秒的替代時間傳球; 1秒的實時傳球:25秒的替補時間傳球;等等... –