Random
複数のスレッド間でクラスの1つのインスタンスを共有することは有効ですか?そしてnextInt(int)
、特に複数のスレッドから呼び出すには?
java.util.concurrent.ThreadLocalRandom
ます。
Random
複数のスレッド間でクラスの1つのインスタンスを共有することは有効ですか?そしてnextInt(int)
、特に複数のスレッドから呼び出すには?
java.util.concurrent.ThreadLocalRandom
ます。
回答:
複数のスレッドで使用された場合でも乱数を生成するという意味で、スレッドセーフです。
Sun / Oracle JVMの実装では、同期されたAtomicLongをシードとして使用して、スレッド間の一貫性を向上させます。ただし、ドキュメント内のすべてのプラットフォームで保証されているようには見えません。
特にnextInt()
呼び出される順序を決定できないため、このような保証を要求するようにプログラムを作成することはありません。
常にではありませんでしたが、スレッドセーフです。
詳細については、http://bugs.sun.com/bugdatabase/view_bug.do?bug_id = 6362070を参照してください。
ドキュメントによると、Math.random()は、複数のスレッドで使用しても安全であることを保証します。しかし、Randomクラスはそうではありません。その場合は、自分で同期する必要があると思います。
はい、ランダムはスレッドセーフです。このnextInt()
メソッドは、(atomic long)を使用して次のシードを生成する保護されたnext(int)
メソッドを呼び出しますAtomicLong seed, nextseed
。AtomicLong
シード生成時のスレッドセーフのために使用されます。
言ったように、それはスレッドの保存ですがjava.util.concurrent.ThreadLocalRandom
、この記事(リンクデッド)に従って使用するのが賢明かもしれません。ThreadLocalRandomはRandomのサブクラスでもあるため、下位互換性があります。
記事は異なるランダムクラスの比較プロファイリング結果をリンク:
java.util.Random
、java.util.concurrent.ThreadLocalRandom
とjava.lang.ThreadLocal<java.util.Random>
。結果は、ThreadLocalRandomの使用が最もパフォーマンスが高く、続いてThreadLocalとRandom自体のパフォーマンスが最も低いことを示しています。
複数のスレッドがすべて同じランダムを使用できないわけではありません。ただし、クラスは明示的にスレッドセーフではなく、シードを介して一連の疑似乱数を維持するためです。複数のスレッドが同じ乱数になる可能性があります。スレッドごとに複数のランダムを作成し、それらを異なる方法でシードすることをお勧めします。
編集:私はSunの実装がAtomicLongを使用していることに気付いたので、それはスレッドセーフであると思います(Peter Lawrey(+1)によっても指摘されています)。
EDIT2:OpenJDKもシードにAtomicLongを使用します。他の人が言っているように、これに頼るのはまだ良くありません。
ランダムがアトミック変数を使用すると仮定せずに問題に対処する方法を次に示します。それがcurrentTime * thread id
将来のある時点で等しい場合でもランダムに衝突する可能性がありますが、それは私のニーズには十分まれです。衝突の可能性を完全に回避するために、各リクエストに一意のクロックタイムスタンプを待機させることができます。
/**
* Thread-specific random number generators. Each is seeded with the thread
* ID, so the sequence of pseudo-random numbers are unique between threads.
*/
private static ThreadLocal<Random> random = new ThreadLocal<Random>() {
@Override
protected Random initialValue() {
return new Random(
System.currentTimeMillis() *
Thread.currentThread().getId());
}
};
(24*60*60*1000)
一部は重要ですか?
(24*60*60*1000)
IDとスレッドほどだった12
のxxxxxxxxxx045
ミリ秒をスレッドと同じ播種されませんでした22
ではxxxxxxxxxx035
ミリ秒。ただし、スレッドIDがインクリメンタルであると想定する正当な理由はなく、明日よりもランダムな時間にスレッドを作成していると考える正当な理由はありません。ここでalgを簡略化し、説明を更新して欠点を特定しました。