デフォルトのjava.time.Clockの実装は、System.currentTimeMillis()に基づいています。ここで例として説明したように、 Monotonically increasing time in Java?、 単調であることは保証されません。Javaに一貫性のある(単調な)クロック実装がありますか?
実際、私は定期的にシステム時間が自動的に数秒前に調整され、Javaクロックもまた戻ってくる状況を経験しています。
//now() returns 2016-01-13T22:34:05.681Z
order.setCreationTime(Instant.now());
//... something happens, order gets cancelled
//now() returns 2016-01-13T22:34:03.123Z
//which is a few seconds before the former one,
//even though the call was performed later - in any reasonable sense.
//The recorded history of events is obviously inconsistent with the real world.
order.setCancelationTime(Instant.now());
1を一方向にのみに行く時間に頼ることができない場合には、イベントの履歴を記録し、分析するように、その後、時間に敏感な事柄を実行することは不可能です。
上記の投稿では、System.nanoTime()は単調である(基本システムでサポートされている場合)。したがって、私のコードをjava.time APIの基底にしたい場合、時間の一方向の流れを保証するために、内部的にnanoTimeを使用するClockが必要です。このようなものが働くかもしれない。それとも?
public class MyClock() extends java.time.Clock {
private final long adjustment;
public MyClock() {
long cpuTimeMillis = System.nanoTime()/1000000;
long systemTimeMillis = System.currentTimeMillis();
adjustment = systemTimeMillis - cpuTimeMillis;
}
@Override
public long millis() {
long currentCpuTimeMillis = System.nanoTime()/1000000;
return currentCpuTimeMillis + adjustment;
}
}
単なるスケッチであり、完全なクロック実装ではありません。そして、適切な実装では、currentTimeMillis()に対して直接ではなく、コンストラクタで渡される別のClockに対しても調整を実行する必要があると思います。
または、既にどこでも単調なクロックの実装がありますか?私は、同じ問題に直面している多くの人々がいたに違いないと思います。
結論
感謝の言葉と答えに感謝します。コメントにはいくつかの興味深い点が散見されているので、ここでそれを要約します。私の元の質問については
1.単調クロック
、はい、逆方向にジャンプするシステム時刻に影響されない単調なクロックを持つことが可能です。そのような実装は上記のSystem.nanoTime()に基づいています。過去にこの問題が発生していましたが、現代の現代システムではうまくいくはずです。このアプローチは、すでにTime4Jライブラリに例えば実装され、その単調なクロックを簡単java.time.Clockに変換することができます。
Clock clock = TemporalType.CLOCK.from(SystemClock.MONOTONIC);
2.適切なシステム時刻制御
それは構成することが可能とITシステム時間管理(unix/linuxのntpd)。システム時間が事実上戻ってこないようにする(必要に応じて遅くなる)ので、システム時間は単調増加に依存し、Javaではclock-magicは必要ありません。
私のアプリはサーバー側であり、私は時間を制御することができるので、私はこのようにします。実際には、自分でインストールした実験環境(ドメインの表面知識のみ)で異常を経験しましたが、ではなく、ntpdateクライアント(時間が同期していない場合は後方にジャンプできます) ntpd(ジャンプバックしないように設定できます)。シーケンスではなく、クロックを使用して
3. 1は、アトミックに生成されたシーケンスからのイベントのシリアル番号を与え、壁に頼らない方が安全であるものを前に何が起こったのか強い関係を追跡する必要がある
クロック。アプリケーションがいくつかのノードで実行されていると、これは唯一のオプションになります(私の場合ではありません)。
時間は単調なものですが、日付はありません。日付は時間を表す人間の構成です。純粋に時間を表現するために何かが必要な場合は、代わりにデータベースシーケンスやその他の信頼できる情報を使用できます。 – Leo
nanoTimeで必要なことを行うことができない場合があります。 http://www.principiaprogramatica.com/?p=16 – Bill
私の[単調時計の実装]のソースを調べることができるかもしれません(http://time4j.net/javadoc-en/net/time4j/SystemClock.html #MONOTONIC)を使用して、いくつかのアイデアをjava.timeベースの時計に転送します。ソース - 参照:https://github.com/MenoData/Time4J/blob/master/core/src/main/java/net/time4j/SystemClock.java –