自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

ThreadLocalRandom類原理分析

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

[[428387]]

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

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ù)新的種子計算隨機數(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; 
  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)); 

Random小結(jié):

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

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

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

這里使用了延遲初始化,在localInit方法中,并沒有初始化種子變量,而是在需要生成隨機數(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); 
  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; 

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

 

責(zé)任編輯:武曉燕 來源: 一個程序員的成長
相關(guān)推薦

2021-05-13 10:40:16

ThreadLocal代碼Java

2022-12-15 08:54:28

JAVA性能JDK

2022-04-13 08:23:31

Golang并發(fā)

2020-10-13 07:35:22

JUC - Count

2023-04-26 08:39:41

Bitmap元素存儲

2012-12-03 16:57:37

HDFS

2015-09-23 16:14:03

Ryu拓撲結(jié)構(gòu)

2022-04-12 08:30:45

TomcatWeb 應(yīng)用Servlet

2023-02-07 09:17:19

Java注解原理

2009-11-06 09:22:46

WCF應(yīng)用

2021-11-26 17:17:43

Android廣播運行原理源碼分析

2017-02-09 13:23:46

2015-06-15 10:12:36

Java原理分析

2021-04-21 15:17:10

WebsocketWsnodejs

2021-08-09 11:15:28

MybatisJavaSpring

2023-10-31 16:00:51

類加載機制Java

2011-06-21 09:22:53

Random類

2009-11-06 13:25:35

Visual Stud

2010-06-29 17:07:10

Linux SNMP代

2022-08-08 07:33:11

自動裝配Java容器
點贊
收藏

51CTO技術(shù)棧公眾號