日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
ThreadLocalRandom類原理分析

本文轉(zhuǎn)載自微信公眾號「一個程序員的成長」,作者一個程序員的成長。轉(zhuǎn)載本文請聯(lián)系一個程序員的成長公眾號。

創(chuàng)新互聯(lián)建站于2013年創(chuàng)立,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項目成都做網(wǎng)站、成都網(wǎng)站建設(shè)網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元漢中做網(wǎng)站,已為上家服務(wù),為漢中各地企業(yè)和個人服務(wù),聯(lián)系電話:028-86922220

1、Random類及其局限性

 
 
 
  1. public int nextInt(int bound) {
  2.     if (bound <= 0)
  3.         throw new IllegalArgumentException(BadBound);
  4.     // 計算新的種子
  5.     int r = next(31);
  6.     int m = bound - 1;
  7.     // 根據(jù)新的種子計算隨機(jī)數(shù)
  8.     if ((bound & m) == 0)  // i.e., bound is a power of 2
  9.         r = (int)((bound * (long)r) >> 31);
  10.     else {
  11.         for (int u = r;
  12.              u - (r = u % bound) + m < 0;
  13.              u = next(31))
  14.             ;
  15.     }
  16.     return r;
  17. }
 
 
 
  1. protected int next(int bits) {
  2.     long oldseed, nextseed;
  3.     // 這是一個原子性的變量
  4.     AtomicLong seed = this.seed;
  5.     do {
  6.         // (1)、獲取老的種子
  7.         oldseed = seed.get();
  8.         // (2)、計算出新的種子
  9.         nextseed = (oldseed * multiplier + addend) & mask;
  10.     // (3)、CAS操作更新老的種子
  11.     } while (!seed.compareAndSet(oldseed, nextseed));
  12.     return (int)(nextseed >>> (48 - bits));
  13. }

Random小結(jié):

  • 面試:多線程下Random存在什么樣的問題?

每個Random實例里面都有一個原子性的種子變量用來記錄當(dāng)前的種子值,當(dāng)要生成新的隨機(jī)數(shù)時需要根據(jù)當(dāng)前的種子計算新的種子并更新種子變量。當(dāng)在多線程環(huán)境下,多個線程會競爭同一個原子變量的更新操作,由于原子變量的更新時CAS操作,同時只有一個線程會成功,所以會造成大量線程進(jìn)行自旋重試,從而降低并發(fā)性能。

可能出現(xiàn)的癥狀:如果并發(fā)請求非常多,自旋鎖一直重試,那么CPU會一直飆升。

2、ThreadLocalRandom

 
 
 
  1. public static ThreadLocalRandom current() {
  2.     if (UNSAFE.getInt(Thread.currentThread(), PROBE) == 0)
  3.         localInit();
  4.     return instance;
  5. }
 
 
 
  1. static final void localInit() {
  2.     int p = probeGenerator.addAndGet(PROBE_INCREMENT);
  3.     int probe = (p == 0) ? 1 : p; // skip 0
  4.     long seed = mix64(seeder.getAndAdd(SEEDER_INCREMENT));
  5.     Thread t = Thread.currentThread();
  6.     UNSAFE.putLong(t, SEED, seed);
  7.     UNSAFE.putInt(t, PROBE, probe);
  8. }

這個方法用來創(chuàng)建ThreadLocalRandom隨機(jī)數(shù)生成器,如果當(dāng)前線程中threadLocalRandomProbe的變量值為0,則說明是第一次調(diào)用current方法,那么就調(diào)用localInit方法初始化種子變量。

這里使用了延遲初始化,在localInit方法中,并沒有初始化種子變量,而是在需要生成隨機(jī)數(shù)的時候再生成種子變量,這是一種優(yōu)化。

 
 
 
  1. static final void localInit() {
  2.     int p = probeGenerator.addAndGet(PROBE_INCREMENT);
  3.     int probe = (p == 0) ? 1 : p; // skip 0
  4.     long seed = mix64(seeder.getAndAdd(SEEDER_INCREMENT));
  5.     Thread t = Thread.currentThread();
  6.     UNSAFE.putLong(t, SEED, seed);
  7.     UNSAFE.putInt(t, PROBE, probe);
  8. }
 
 
 
  1. final long nextSeed() {
  2.     Thread t; long r; // read and update per-thread seed
  3.     // 生成新種子(獲取當(dāng)前線程種子 + 種子增量)
  4.     UNSAFE.putLong(t = Thread.currentThread(), SEED,
  5.                    r = UNSAFE.getLong(t, SEED) + GAMMA);
  6.     return r;
  7. }

mix32是一個固定的算法,這里重點看下nextSeed方法,當(dāng)?shù)谝淮握{(diào)用的時候進(jìn)行初始化,獲取當(dāng)前線程threadLocalRandomSeed的值(第一次默認(rèn)值為0) + 種子增量,如果不是第一次那么獲取舊種子的值 + 種子增量生成新的種子變量并設(shè)置回去。這樣的話多線程環(huán)境下就避免了競爭,因為threadLocalRandomSeed是Thread的一個變量,屬于線程級別。


網(wǎng)站欄目:ThreadLocalRandom類原理分析
新聞來源:http://www.5511xx.com/article/dpohecc.html