亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

前言

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

Random的使用

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

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

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

實現(xiàn)原理

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

可以看到在構(gòu)造方法中,根據(jù)當前時間seed生成了一個AtomicLong類型的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));
}

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

小結(jié):

可以看出在next(int bits)方法中,對AtomicLong進行了CAS操作,如果失敗則循環(huán)重試。 很多人一看到CAS,因為不需要加鎖,第一時間就想到了高性能、高并發(fā)。 但是在這里,卻成為了我們多線程并發(fā)性能的瓶頸。 可以想象,當我們有多個線程執(zhí)行CAS時,只有一個線程一定會失敗,其他的會繼續(xù)循環(huán)執(zhí)行CAS操作。 當并發(fā)線程較多時,性能就會下降。

ThreadLocalRandom的使用

JDK1.7之后,提供了一個新類ThreadLocalRandom來替代Random。

實現(xiàn)原理

我們先來看下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);
}

如果沒有初始化,先進行初始化,這里我們的seed不再是全局變量了。 我們的線程中有三個變量:

/** 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:這是我們用來控制隨機數(shù)的種子。
  • threadLocalRandomProbe:這個就是ThreadLocalRandom,用來控制初始化。
  • threadLocalRandomSecondarySeed:這是二級種子。

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

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

可以看出,由于每個線程都維護自己的seed,所以此時不需要CAS,直接進行put。 這里通過線程間的隔離來減少并發(fā)沖突,所以ThreadLocalRandom的性能非常高。

性能對比

通過基準工具JMH測試:

@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();
   }
	
}

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

顯而易見,無論線程數(shù)量是多少,ThreadLocalRandom性能是遠高于Random

總結(jié)

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

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

相關(guān)文章

  • windows7配置java環(huán)境變量的圖文教程

    windows7配置java環(huán)境變量的圖文教程

    這篇文章主要介紹了windows7配置java環(huán)境變量的教程,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-02-02
  • 簡單了解synchronized和lock的區(qū)別

    簡單了解synchronized和lock的區(qū)別

    這篇文章主要介紹了簡單了解synchronized和lock的區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-09-09
  • Java方法調(diào)用解析靜態(tài)分派動態(tài)分派執(zhí)行過程

    Java方法調(diào)用解析靜態(tài)分派動態(tài)分派執(zhí)行過程

    這篇文章主要為大家介紹了Java方法調(diào)用解析靜態(tài)分派動態(tài)分派執(zhí)行過程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • Java中獲取泛型類型信息的方法

    Java中獲取泛型類型信息的方法

    本文主要介紹了Java中獲取泛型類型信息的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-03-03
  • 使用SpringBoot開發(fā)Restful服務實現(xiàn)增刪改查功能

    使用SpringBoot開發(fā)Restful服務實現(xiàn)增刪改查功能

    Spring Boot是由Pivotal團隊提供的全新框架,其設計目的是用來簡化新Spring應用的初始搭建以及開發(fā)過程。這篇文章主要介紹了基于SpringBoot開發(fā)一個Restful服務,實現(xiàn)增刪改查功能,需要的朋友可以參考下
    2018-01-01
  • 淺析Alibaba Nacos注冊中心源碼剖析

    淺析Alibaba Nacos注冊中心源碼剖析

    這篇文章主要介紹了淺析Alibaba Nacos注冊中心源碼剖析,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-05-05
  • Java常用字符串工具類 字符串智能截取(3)

    Java常用字符串工具類 字符串智能截?。?)

    這篇文章主要為大家詳細介紹了Java常用字符串工具類,字符串的智能截取,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • java使用POI操作excel文件

    java使用POI操作excel文件

    本文主要介紹了java使用POI操作excel文件,實現(xiàn)批量導出和導入的方法。具有很好的參考價值。下面跟著小編一起來看下吧
    2017-03-03
  • java的if else語句入門指南(推薦)

    java的if else語句入門指南(推薦)

    下面小編就為大家?guī)硪黄猨ava的if else語句入門指南(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-06-06
  • Spring注解@Conditional案例解析

    Spring注解@Conditional案例解析

    這篇文章主要介紹了Spring注解@Conditional案例解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-10-10

最新評論