4

毎秒 1000 個のエンティティを作成するプロセスがあるとします。これらのエンティティごとに、セッターを呼び出します。

newEntity.setDate(new Date());

1) 2 つのエンティティが同じ日付を受け取る可能性はありますか? または、日付フィールドに対して一意の識別子の効果が得られると想定しても安全ですか?

2) 質問 #1 の答えが「はい」の場合 - ちょっとした調整をしましょう: 関数を作成しましょう:

public static synchronized Date getDate() {
     return new Date();
}

それは今動作しますか?

newEntity.setDate(getDate());

3) どうですか

System.nanoTime()?

編集 4)どうですか:

public static synchronized Date getDate() {
     Thread.Sleep(1000);
     return new Date();
}

ありがとう。

4

4 に答える 4

10

簡単なテストで、 を 2 回連続して呼び出すとnew Date()、同じ日付が返されることがわかります。メソッドを同期させても違いはありません。

一意の ID だけが必要な場合は、新しい IDにAtomicInteger counterandを使用できます。return counter.getAndIncrement();

ps:System.nanotime()解像度は OS とプロセッサに依存し、一般に 2 つの連続した呼び出しでも同じ結果が返されるほど低いため、使用しても役に立ちません。


編集

同期メソッドで 1 秒間スリープするという 4 番目の提案は、おそらく単一性の問題を解決するでしょう (ただし、yshavit で指摘されているように、javadoc には何も保証されていません)。ただし、日付を一意の ID として使用すること自体が悪い考えであることに注意してください。日付は変更可能であるため、呼び出し元のコードがsetTimeメソッドで ID を (誤って、または意図的に) 変更する可能性があります。

最後に、ID を日付に関連させたい場合は、エポック以降のミリ秒を表す long を使用して、既存の ID を追跡できます。次のようになります。

private static final Set<Long> usedIds = new HashSet<> ();
public static synchronized long getUniqueId() {
    long millis;
    do {
        millis = System.currentTimeMillis();
    } while (!usedIds.add(millis));
    return millis;
}
于 2013-07-31T12:51:41.223 に答える
4

Dateミリ秒の精度があります。要するに、「1 ミリ秒で 2 回呼び出すことは可能new Date()ですか? 答えは明らかにイエスです。さらに、System.currentTimeMillis() はミリ秒まで完全に正確ではないため、問題が悪化するだけです。

AtomicInteger(または)からの単純なカウンターを使用したほうがよいでしょうAtomicLong

さらに、これは「契約による設計」という考え方の良い練習になります。currentTimeMillisどちらの仕様もnanoTime、一意の数値を返すとは言っていないため、一意の数値を返すとは想定できません (実際、nanoTime の Javadoc では、「値が変更される頻度については保証されていません」と具体的に述べられています)。今日のコンピューターで起こったとしても (おそらくそうではないでしょう)、CPU が 5 年で高速になりnanoTime()、1 秒間に 1 兆回も呼び出せるようになったらどうなるでしょうか?

今日たまたま観察したことではなく、約束されたことを続けてください(約束を信頼していると仮定して!)。これは一般的に当てはまりますが、特にタイミングや同時実行性に関連するものには当てはまります。

于 2013-07-31T12:53:12.257 に答える
0

残念ながら 1. は良い解決策ではありませ
ん。
同期された方法では、正しい粒度(1ミリ秒)でスリープを追加できますが、とにかく非常に醜いです。
あなたの他の提案。
System.nanotime() 私は今あなたの uuid であるべきだと思います。
この場合の回避策は、遅延を 1 ナノ秒に設定し、次のようにすることです。

long start = System.nanotime();  
while(start + delay < System.nanoTime());  
于 2013-07-31T13:09:50.177 に答える
0

1) CPU が十分に高速である場合、はい、2 つのエンティティが同じ時間を表す異なるオブジェクトを受け取る可能性があります(つまり、希望どおりに動作しません)。

2) 繰り返しますが、CPU が十分に高速な場合は機能しません。

于 2013-07-31T12:51:40.623 に答える