A、ランダムクラス
パブリック クラスRandomTest { 公共 静的 ボイドメイン(文字列[]引数){ ランダムランダム = 新しいランダム(); 以下のために(INT I = 0; I <10; I ++ ){ System.out.printlnは(にRandom.nextInt())。 } } } / * * nextInt()源码 * / 保護 INT(次のint ビット){ 長いオールドシード、nextseed。 AtomicLong種子 = この.seed。 やる{ オールドシード =seed.get(); nextseed =(+加数乗数オールドシード*)&マスク; } しばらく(seed.compareAndSet(オールドシード、nextseed)!); // nextseed取得CAS保証アトミック、マルチスレッド意志の自己スレッドを多数使用してスピン再試行は、並行性を低減します。 リターン(INT)(nextseed >>>(48 -ビット));}
二、ThreadLocalRandomクラス
ランダムには、特定のソース文は以下の、それぞれのスレッドのインスタンスで独自の種子を保存する、ThreadLocalのの実装に似nextIntを、書き換え継承されました。
// 次の三つ最初に初期化されていないフィールドが排他的にされている // クラスjava.util.concurrent.ThreadLocalRandomによって管理されます。これら // フィールドはで高性能のPRNGを構築するために使用されている // 並行コード、そして私たちは偶然のフォルス・シェアリングを危険にさらすことはできません。 // したがって、フィールドは@Contendedで単離されます。 / ** ThreadLocalRandomの現在のシード* / @ sun.misc.Contended( "TLRは" ) 長いthreadLocalRandomSeed。 / ** プローブハッシュ値。ゼロ以外threadLocalRandomSeedは初期化された場合* / (@ sun.misc.Contended "TLR" ) int型threadLocalRandomProbe; / ** 公共ThreadLocalRandom配列から分離二種* / @ sun.misc.Contended( "TLR" ) int型 threadLocalRandomSecondarySeed。
ThreadLocalRandom達成
パブリック クラスThreadLocalRandomTest { 公共 静的 ボイドメイン(文字列[]引数){ ThreadLocalRandomランダム = ThreadLocalRandom.current(); のための(INT I = 0; I <10; I ++ ){ System.out.printlnは(にRandom.nextInt( 5 ) ); } } } / ** *シードに記憶された各スレッドから取得nextseed、ネジ付きスペーサである * / 最終 ロングnextSeed(){ スレッドT; 長い R&LT; // 読み取りと更新ごとSEEDスレッド UNSAFE.putLong (T =Thread.currentThread()、SEED、 R = UNSAFE.getLong(T、SEED)+ GAMMA)。//Thread.currentThread.threadLocalRandomSeed 戻りR; }
ThreadLocalRandom主要なソースモジュール
1.unsafe初期化
// 安全でない力学 プライベート 静的 最終sun.misc.Unsafe UNSAFE。 プライベート 静的 最終 長いSEED。 プライベート 静的 最終 長いPROBE。 プライベート 静的 最終 長いSECONDARY。 静的{ 試み{ UNSAFE = sun.misc.Unsafe.getUnsafe()。 クラス <?> TK =スレッド。クラス。 SEED = UNSAFE.objectFieldOffset(tk.getDeclaredField(「threadLocalRandomSeed" )); PROBE = UNSAFE.objectFieldOffset(tk.getDeclaredField( " threadLocalRandomProbe " )); SECONDARY = UNSAFE.objectFieldOffset(tk.getDeclaredField( " threadLocalRandomSecondarySeed " )); } キャッチ(例外電子){ スロー 新しいエラー(E); } }
2.現在の静的メソッドを提供建設民営化の方法は、シングルトンを確実にインスタンス化
/ ** コンストラクタは、静的シングルトンに使用* / プライベートThreadLocalRandom(){ 初期化 = 真。// スーパー()の呼び出し時に偽 } / ** *戻り値現在のスレッドの{ @code ThreadLocalRandom}。* / パブリック 静的ThreadLocalRandom電流(){ 場合(UNSAFE.getInt(にThread.currentThread()、PROBE)== 0)// 当前线程スレッド实例中threadLocalRandomProbe为0初始化シード localInit()。 戻り値のインスタンス。 } / ** *現在のスレッドの初期化スレッドフィールド。のみ呼び出さ Thread.threadLocalRandomProbeがゼロであるときことを示し、* *スレッドローカルシード値を生成する必要があります。でも、という注意 初期化が純粋にスレッドローカルにしているが*、我々がする必要がある *値を初期化する(静的)、原子発電に依存しています。 * / 静的 最終 ボイドlocalInit(){ int型、P = probeGenerator.addAndGet(PROBE_INCREMENT)。 int型プローブ=(P == 0)?1:P。// 不为0、保证单例 長いシード= mix64(seeder.getAndAdd(SEEDER_INCREMENT))。 スレッドトン =Thread.currentThread(); UNSAFE.putLong(T、SEED、SEED); // threadLocalRandomSeedにおける現在のスレッドに保存 UNSAFE.putInt(T、プローブ、プローブ); // }
3.乱数
/ ** *擬似乱数{返し@codeのゼロ(含む)の間の整数}値を *と指定された結合(排他的)。 * * @paramは上限(排他的)を結合しました。正でなければなりません。 * @return 擬似乱数{ @codeのゼロとの間INT}値を *(含む)と結合した(排他的) * @throws {IllegalArgumentExceptionを@codeが結合し}が正でない * / パブリック INTが nextInt(intは結合){ 場合(結合< = 0 ) スロー 新しいはIllegalArgumentException(BadBound)。 INT R = mix32(nextSeed())。//重点下一个シード INT M =結合- 1 。 もし((M&結合)== 0)// 2つの累乗 R&= M。 他 { //は過剰表現候補リジェクト 用(INT U = R >>> 1 、 U + M - (R = U%結合)<0 、 U = mix32(nextSeed())は、1 >>> ) 。 } 戻りR。 } 最終 長いですnextSeed(){ スレッドT。長い R; // 読み取りおよび更新スレッドごとの種子 UNSAFE.putLong(T = にThread.currentThread()、SEED、 R = UNSAFE.getLong(T、SEED)+ GAMMA)。//取得是当前线程中的threadLocalRandomSeed变量 戻りR; }