最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java生成隨機(jī)數(shù)之Random與ThreadLocalRandom性能比較詳解

 更新時(shí)間:2022年12月15日 08:28:19   作者:JAVA旭陽(yáng)  
大家項(xiàng)目中如果有生成隨機(jī)數(shù)的需求,我想大多都會(huì)選擇使用Random來(lái)實(shí)現(xiàn),它內(nèi)部使用了CAS來(lái)實(shí)現(xiàn)。?實(shí)際上,JDK1.7之后,提供了另外一個(gè)生成隨機(jī)數(shù)的類(lèi)ThreadLocalRandom,那么他們二者之間的性能是怎么樣的呢?本文就來(lái)詳細(xì)說(shuō)說(shuō)

前言

大家項(xiàng)目中如果有生成隨機(jī)數(shù)的需求,我想大多都會(huì)選擇使用Random來(lái)實(shí)現(xiàn),它內(nèi)部使用了CAS來(lái)實(shí)現(xiàn)。 實(shí)際上,JDK1.7之后,提供了另外一個(gè)生成隨機(jī)數(shù)的類(lèi)ThreadLocalRandom,那么他們二者之間的性能是怎么樣的呢?

Random的使用

Random類(lèi)是JDK提供的生成隨機(jī)數(shù)的類(lèi), 這個(gè)類(lèi)不是隨機(jī)的,而是偽隨機(jī)的。什么是偽隨機(jī)呢? 偽隨機(jī)是指生成的隨機(jī)數(shù)是有一定規(guī)律的,這個(gè)規(guī)律出現(xiàn)的周期因偽隨機(jī)算法的優(yōu)劣而異。 一般來(lái)說(shuō),周期比較長(zhǎng),但可以預(yù)見(jiàn)。 我們可以通過(guò)以下代碼簡(jiǎn)單地使用 Random:

Random中有很多方法。 這里我們就分析比較常見(jiàn)的nextInt()nextInt(int bound)方法。

  • nextInt()會(huì)計(jì)算int范圍內(nèi)的隨機(jī)數(shù),
  • nextInt(int bound)會(huì)計(jì)算[0,bound) 之間的隨機(jī)數(shù),左閉右開(kāi)。

實(shí)現(xiàn)原理

Random類(lèi)的構(gòu)造函數(shù)如下圖所示:

可以看到在構(gòu)造方法中,根據(jù)當(dāng)前時(shí)間seed生成了一個(gè)AtomicLong類(lèi)型的seed

public int nextInt() {
    return next(32);
}

這里面直接調(diào)用了next()方法,傳入了32,這里的32是指Int的位數(shù)。

protected int next(int bits) {
    long oldseed, nextseed;
    AtomicLong seed = this.seed;
    do {
        oldseed = seed.get();
        nextseed = (oldseed * multiplier + addend) & mask;
    } while (!seed.compareAndSet(oldseed, nextseed));
    return (int)(nextseed >>> (48 - bits));
}

這里會(huì)根據(jù)seed的當(dāng)前值,通過(guò)一定的規(guī)則(偽隨機(jī))計(jì)算出下一個(gè)seed,然后進(jìn)行CAS。 如果CAS失敗,繼續(xù)循環(huán)上述操作。 最后根據(jù)我們需要的位數(shù)返回。

小結(jié):

可以看出在next(int bits)方法中,對(duì)AtomicLong進(jìn)行了CAS操作,如果失敗則循環(huán)重試。 很多人一看到CAS,因?yàn)椴恍枰渔i,第一時(shí)間就想到了高性能、高并發(fā)。 但是在這里,卻成為了我們多線程并發(fā)性能的瓶頸。 可以想象,當(dāng)我們有多個(gè)線程執(zhí)行CAS時(shí),只有一個(gè)線程一定會(huì)失敗,其他的會(huì)繼續(xù)循環(huán)執(zhí)行CAS操作。 當(dāng)并發(fā)線程較多時(shí),性能就會(huì)下降。

ThreadLocalRandom的使用

JDK1.7之后,提供了一個(gè)新類(lèi)ThreadLocalRandom來(lái)替代Random。

實(shí)現(xiàn)原理

我們先來(lái)看下current()方法。

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

如果沒(méi)有初始化,先進(jìn)行初始化,這里我們的seed不再是全局變量了。 我們的線程中有三個(gè)變量:

/** The current seed for a ThreadLocalRandom */
@sun.misc.Contended("tlr")
long threadLocalRandomSeed;

/** Probe hash value; nonzero if threadLocalRandomSeed initialized */
@sun.misc.Contended("tlr")
int threadLocalRandomProbe;

/** Secondary seed isolated from public ThreadLocalRandom sequence */
@sun.misc.Contended("tlr")
int threadLocalRandomSecondarySeed;
  • threadLocalRandomSeed:這是我們用來(lái)控制隨機(jī)數(shù)的種子。
  • threadLocalRandomProbe:這個(gè)就是ThreadLocalRandom,用來(lái)控制初始化。
  • threadLocalRandomSecondarySeed:這是二級(jí)種子。

關(guān)鍵代碼如下:

UNSAFE.putLong(t = Thread.currentThread(), SEED,r=UNSAFE.getLong(t, SEED) + GAMMA);

可以看出,由于每個(gè)線程都維護(hù)自己的seed,所以此時(shí)不需要CAS,直接進(jìn)行put。 這里通過(guò)線程間的隔離來(lái)減少并發(fā)沖突,所以ThreadLocalRandom的性能非常高。

性能對(duì)比

通過(guò)基準(zhǔn)工具JMH測(cè)試:

@BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations=3, time = 5, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations=3,time = 5)
@Threads(4)
@Fork(1)
@State(Scope.Benchmark)
public class Myclass {
   Random random = new Random();
   ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();

   @Benchmark
   public int measureRandom(){
       return random.nextInt();
   }
   @Benchmark
   public int threadLocalmeasureRandom(){
       return threadLocalRandom.nextInt();
   }
	
}

運(yùn)行結(jié)果如下圖所示,最左邊是并發(fā)線程的數(shù)量:

顯而易見(jiàn),無(wú)論線程數(shù)量是多少,ThreadLocalRandom性能是遠(yuǎn)高于Random

總結(jié)

本文講解了JDK中提供的兩種生成隨機(jī)數(shù)的方式,一個(gè)是JDK 1.0引入的Random類(lèi),另外一個(gè)是JDK1.7引入的ThreadLocalRandom類(lèi),由于底層的實(shí)現(xiàn)機(jī)制不同,ThreadLocalRandom的性能是遠(yuǎn)高于Random,建議后面大家在技術(shù)選型的時(shí)候優(yōu)先使用ThreadLocalRandom

到此這篇關(guān)于Java生成隨機(jī)數(shù)之Random與ThreadLocalRandom性能比較詳解的文章就介紹到這了,更多相關(guān)Java Random ThreadLocalRandom內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(33)

    Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(33)

    下面小編就為大家?guī)?lái)一篇Java基礎(chǔ)的幾道練習(xí)題(分享)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧,希望可以幫到你
    2021-07-07
  • Java Enum和String及int的相互轉(zhuǎn)化示例

    Java Enum和String及int的相互轉(zhuǎn)化示例

    這篇文章主要介紹了Java Enum和String及int的相互轉(zhuǎn)化示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • 深入講解基于JDK的動(dòng)態(tài)代理機(jī)制

    深入講解基于JDK的動(dòng)態(tài)代理機(jī)制

    眾所周知相比于靜態(tài)代理,動(dòng)態(tài)代理避免了開(kāi)發(fā)人員編寫(xiě)各個(gè)繁鎖的靜態(tài)代理類(lèi),下面這篇文章主要給大家介紹了關(guān)于基于JDK的動(dòng)態(tài)代理機(jī)制的相關(guān)資料,文中通過(guò)圖文以及示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2018-07-07
  • 關(guān)于javax.validation.constraints的超詳細(xì)說(shuō)明

    關(guān)于javax.validation.constraints的超詳細(xì)說(shuō)明

    這篇文章主要給大家介紹了關(guān)于javax.validation.constraints的超詳細(xì)說(shuō)明,文中通過(guò)代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2025-07-07
  • Spring?中?PageHelper?不生效問(wèn)題及解決方法

    Spring?中?PageHelper?不生效問(wèn)題及解決方法

    這篇文章主要介紹了Spring?中?PageHelper?不生效問(wèn)題,使用這個(gè)插件時(shí)要注意版本的問(wèn)題,不同的版本可能 PageHelper 不會(huì)生效,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-12-12
  • 基于SpringBoot實(shí)現(xiàn)QQ郵箱驗(yàn)證碼注冊(cè)功能

    基于SpringBoot實(shí)現(xiàn)QQ郵箱驗(yàn)證碼注冊(cè)功能

    QQ 郵箱是由騰訊公司推出的一款免費(fèi)郵箱服務(wù),它提供了完整的郵件發(fā)送和接收功能,并且還支持多種郵件格式和附件類(lèi)型,QQ 郵箱還具有強(qiáng)大的反垃圾郵件功能,可以有效地過(guò)濾垃圾郵件,并保護(hù)用戶隱私和安全,所以本文給大家介紹了基于SpringBoot實(shí)現(xiàn)QQ郵箱驗(yàn)證碼注冊(cè)功能
    2024-11-11
  • idea使用jclasslib插件查看字節(jié)碼

    idea使用jclasslib插件查看字節(jié)碼

    這篇文章主要為大家介紹了idea使用jclasslib插件查看字節(jié)碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • 利用Java8 Optional如何避免空指針異常詳解

    利用Java8 Optional如何避免空指針異常詳解

    Optional可以讓你的代碼具有可讀性,且會(huì)避免出現(xiàn)空指針異常。 下面這篇文章主要給大家介紹了關(guān)于利用Java8 Optional如何避免空指針異常的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。
    2018-01-01
  • Springboot中yml文件沒(méi)有葉子圖標(biāo)的解決

    Springboot中yml文件沒(méi)有葉子圖標(biāo)的解決

    這篇文章主要介紹了Springboot中yml文件沒(méi)有葉子圖標(biāo)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • 詳談Java8新特性泛型的類(lèi)型推導(dǎo)

    詳談Java8新特性泛型的類(lèi)型推導(dǎo)

    這篇文章我們來(lái)看一篇關(guān)于Java8新特性之泛型的類(lèi)型推導(dǎo),希望這篇文章能夠讓各位深入到了解到關(guān)于Java8新特性之泛型的類(lèi)型用法,有需要的朋友們下面來(lái)一起看看吧。
    2016-09-09

最新評(píng)論

民乐县| 正安县| 安徽省| 全州县| 黄龙县| 藁城市| 册亨县| 上高县| 高雄县| 大港区| 金川县| 讷河市| 岑巩县| 清徐县| 大悟县| 青浦区| 兴山县| 肥乡县| 肥东县| 宜章县| 大丰市| 苍梧县| 万宁市| 和平县| 敦煌市| 丰原市| 昭苏县| 专栏| 杂多县| 论坛| 永仁县| 谢通门县| 兰州市| 武胜县| 京山县| 密山市| 时尚| 镇康县| 桐柏县| 临沂市| 双城市|