Java実行予定実行プログラムを使用しているときに遭遇した特有の問題があり、私が経験したことが正常かどうか疑問に思っていました。Java実行予定者の精度
私は、定義済みの5秒間に実行されるタスクをスケジュールする必要があります。これらのタスクの実行には5秒以上かかることが予想されますが、実行する時間が5秒を下回ると、バックアップされたタスクのリストはすばやく連続して実行される必要があります。タスクを実行するときは、元の実行予定時刻が何であるかを知ることが重要です(scheduledExecutionTime()
はjava.util.TimerTask
と考える)。最後に、予定と実際の時間の違いを追跡して、スケジュールが「漂流」している時期とその程度を特定する必要があります。
これまでのところ私は、Java実行プログラムを使用してこのすべてを実装している、と以下のクラスは、一般的な考え方を示しています。上記のコードを実行する
public class ExecutorTest {
public static final long PERIOD = 5000;
public static void main(String[] args) {
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(
new Command(), 0, PERIOD, TimeUnit.MILLISECONDS);
}
private static final class Command implements Runnable {
long timestamp = 0;
public void run() {
long now = System.currentTimeMillis();
if (timestamp == 0) {
timestamp = now;
}
// Drift is the difference between scheduled time and execution time
long drift = now - timestamp;
String format = "Ran at %1$tF %<tT,%<tL; drift: %2$dms";
System.out.println(String.format(format, now, drift));
timestamp += PERIOD;
}
}
}
は、理想的に近いべきであるドリフト(することを示しています0を可能な限り)は数秒間変動します。その結果、早すぎたり遅く実行されたタスクが発生します。私は約150分のためにこれを実行した結果からグラフを作成しました:
をだから私の最初の質問は、これが正常であるかどうかです。私の環境は、32ビットのWindows XPとJava 1.5 update 21(ただし、Java 6 update 22では同様の結果が得られます)で構成されています。
第2の問題は、ドリフトの量を減らす簡単な方法があるかどうかです。私が単純なjava.util.Timer
、あるいはちょうどThread.sleep()
を使用すると、ドリフトは存在しません。
最後に、スケジュールされたエグゼキュータを使用しているときに、スケジュールされた実行時間を追跡する優れた方法はありますか?