6

1000 秒ごとに (たとえば) タスクを実行したいと考えています。

だから私たちは持っています

timer.scheduleAtFixedRate(task, delay, interval);

ほとんどの場合、これで問題なく動作します。ただし、これは組み込みシステムであり、ユーザーはリアルタイム クロックを変更できます。タイマーを設定した後に過去の時刻に設定した場合、タイマーは元のリアルタイムの日付/時刻まで実行されないようです。したがって、3 日間戻した場合、タイマーは 3 日間実行されません :(

これは許容される動作ですか、それとも Java ライブラリの欠陥ですか? Oracle javadocs は、依存関係について、またはシステムクロックの基になる値については何も言及していないようです。

許容できる場合、この時計の変更をどのように見つけて、タイマーを再スケジュールしますか?

4

2 に答える 2

18

Timerfor Java 1.7のソースを見るとSystem.currentTimeMillis()、タスクの次の実行を決定するために使用されているようです。

しかし、 のソースを見ると、ScheduledThreadPoolExecutorを使用していますSystem.nanoTime()

つまり、の代わりに使用すると、その動作は見られませんTimer。作成するには、たとえば を使用しますExecutors.newScheduledThreadPool()

この動作が見られないのは、ドキュメントの説明が原因ですSystem.nanoTime()

このメソッドは、経過時間を測定するためにのみ使用でき、システム時間またはウォールクロック時間の他の概念とは関係ありません。返される値は、固定されているが任意の起点時刻からのナノ秒を表します[強調鉱山]。

これが のバグかどうかについてはTimer、おそらく...

a とは異なりScheduledExecutorService、 aTimerは絶対時間をサポートしていることに注意してくださいSystem.currentTimeMillis()。また、1.5 でのみ表示されTimerますが、Java 1.3 から存在しています。System.nanoTime()

しかし、使用の結果はSystem.currentTimeMillis()Timerシステムの日付/時刻に敏感です...そして、それはjavadocに記載されていません。

于 2013-07-11T08:18:30.037 に答える
5

ここで報告されていますhttp://bugs.sun.com/view_bug.do?bug_id=4290274

同様に、システム クロックがより遅い時刻に設定されている場合、実行されなかったタスクを遅延なく「追いつく」ために、タスクを複数回実行できます。まさにこれは、コンピューターがスタンバイ/休止状態に設定され、アプリケーションが再開されたときに発生します (これが私が見つけた方法です)。

この動作は、タイマー スレッドを一時停止して再開することにより、Java デバッガーでも確認できます。

于 2013-07-31T08:40:04.850 に答える