web-dev-qa-db-ja.com

Javaで一意のタイムスタンプを作成する

Javaで、その特定のVMインスタンスで一意であることが保証されているタイムスタンプ(ミリ秒単位)を作成する必要があります。つまり、System.currentTimeMillis()のスループットを調整する方法が必要です。ミリ秒ごとに最大で1つの結果が返されます。それを実装する方法について何かアイデアはありますか?

13
Yrlec

これにより、重複することなく、現在の時刻にできるだけ近い時刻が得られます。

private static final AtomicLong LAST_TIME_MS = new AtomicLong();
public static long uniqueCurrentTimeMS() {
    long now = System.currentTimeMillis();
    while(true) {
        long lastTime = LAST_TIME_MS.get();
        if (lastTime >= now)
            now = lastTime+1;
        if (LAST_TIME_MS.compareAndSet(lastTime, now))
            return now;
    }
}

1ミリ秒あたり1つのIDの制限を回避する1つの方法は、マイクロ秒のタイムスタンプを使用することです。つまり、currentTimeMSに1000を掛けます。これにより、1ミリ秒あたり1000のIDが許可されます。

注:たとえばNTP修正のために時間が逆行した場合、時間は追いつくまで、呼び出しごとに1ミリ秒で進行します。;)

37
Peter Lawrey

精度を高めるためにSystem.nanoTime()を使用できます

以下を試してみましたが、値が異なるたびに、常に一意であるとは限りません。

public static void main(String[] args) {
        long time1 = System.nanoTime();
        long time2 = System.nanoTime();
        long time3 = System.nanoTime();
        System.out.println(time1);
        System.out.println(time2);
        System.out.println(time3);
    }

もう1つの方法は、時間が重要ではなく、一意の番号が必要な場合は、一意の番号にAtomicInteger/AtomicLongクラスを使用することです。これは、おそらくより適切な選択です。

4
fmucar

解決策を探しているときに、[〜#〜] ulib [〜#〜](Universally Unique Lexicographically Sortable Identifier)https://github.com/huxi/sulky/tree/master/sulky-ulid/

長くはありませんが、UUIDよりも短くなっています。

ULID:

  • UUID/GUIDのミリ秒あたり1.21e + 24の一意のULIDと互換性があります(正確には1,208,925,819,614,629,174,706,176)
  • 辞書式順序でソート可能
  • 36文字のUUIDではなく、26文字の文字列として正規にエンコードされます
  • 効率と読みやすさを向上させるためにCrockfordのbase32を使用(文字あたり5ビット)
  • 大文字小文字を区別しません
  • 特殊文字なし(URLセーフ)
2
Marian Venin

利用可能な最も正確なシステムタイマーであるSystem.nanoTime()を使用し、それを100万で割ってミリ秒を取得できます。更新の頻度について正式な保証はありませんが、1ミリ秒に1回よりもはるかに頻繁に(大きさのオーダーで)更新されると想定するのが妥当だと思います。もちろん、ミリ秒未満の間隔で整数のタイムスタンプを作成する場合、それらすべてを一意にすることはできません。

絶対値nanoTime()は任意であることに注意してください。絶対時間を必要とする場合は、なんらかの方法で調整します。つまり、開始時にcurrentTimeMillis()と比較します。

1
Joonas Pulakka

_Java.util.UUID_を利用して、timestamp()clockSequence()を利用できますか?

_Method Summary
    int clockSequence() 
        The clock sequence value associated with this UUID.
    long timestamp() 
        The timestamp value associated with this UUID.
_

詳細はこちら: http://docs.Oracle.com/javase/1.5.0/docs/api/Java/util/UUID.html

0
user379305