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

關(guān)于java.util.Random的實(shí)現(xiàn)原理詳解

 更新時(shí)間:2017年08月30日 09:46:49   作者:jijs  
Java實(shí)用工具類庫(kù)中的類java.util.Random提供了產(chǎn)生各種類型隨機(jī)數(shù)的方法,下面這篇文章主要給大家介紹了關(guān)于java.util.Random實(shí)現(xiàn)原理的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。

概述

java.util.Random可以產(chǎn)生int、long、float、double以及Goussian等類型的隨機(jī)數(shù)。這也是它與java.lang.Math中的方法Random()最大的不同之處,后者只產(chǎn)生double型的隨機(jī)數(shù)。

該類的實(shí)例被用于生成偽隨機(jī)數(shù)的流。該類使用一個(gè) 48 位的種子,它被一個(gè)線性同余公式所修改。如果 Random 的兩個(gè)實(shí)例用同一種子創(chuàng)建,對(duì)每個(gè)實(shí)例完成同方法調(diào)用序列它們將生成和返回相同的數(shù)序列成同一方法調(diào)用序列,它們將生成和返回相同的數(shù)序列。

示例

public class RandomTest {
 public static void main(String[] args) {
 testRandom();
 System.out.println("---------------------");
 testRandom();
 System.out.println("---------------------");
 testRandom();
 }
 
 public static void testRandom(){
 Random random = new Random(1);
 for(int i=0; i<5; i++){
  System.out.print(random.nextInt()+"\t");
 }
 System.out.println("");
 }
}

輸出結(jié)果:


從結(jié)果中發(fā)現(xiàn),只要種子一樣,獲取的隨機(jī)數(shù)的序列就是一致的。是一種偽隨機(jī)數(shù)的實(shí)現(xiàn),而不是真正的隨機(jī)數(shù)。

Random 源碼分析

Random 類結(jié)構(gòu)

class Random implements java.io.Serializable {
 private final AtomicLong seed;

 private static final long multiplier = 0x5DEECE66DL;
 private static final long addend = 0xBL;
 private static final long mask = (1L << 48) - 1;
 private static final AtomicLong seedUniquifier = new AtomicLong(8682522807148012L);

有參構(gòu)造方法

public Random(long seed) {
 if (getClass() == Random.class)
  this.seed = new AtomicLong(initialScramble(seed));
 else {
  // subclass might have overriden setSeed
  this.seed = new AtomicLong();
  setSeed(seed);
 }
}

private static long initialScramble(long seed) {
 return (seed ^ multiplier) & mask;
}

通過(guò)傳入一個(gè)種子,來(lái)生成隨機(jī)數(shù),通過(guò)上面的例子發(fā)現(xiàn),種子一樣產(chǎn)生的隨機(jī)數(shù)序列一樣,如果每次使用想產(chǎn)生不一樣的序列,那就只能每次傳入一個(gè)不一樣的種子。

無(wú)參構(gòu)造方法

public Random() {
 this(seedUniquifier() ^ System.nanoTime());
 }
private static long seedUniquifier() {
 // L'Ecuyer, "Tables of Linear Congruential Generators of
 // Different Sizes and Good Lattice Structure", 1999
 for (;;) {
  long current = seedUniquifier.get();
  long next = current * 181783497276652981L;
  if (seedUniquifier.compareAndSet(current, next))
   return next;
 }
}

通過(guò)源碼發(fā)現(xiàn),無(wú)參的構(gòu)造方法,里面幫我們自動(dòng)產(chǎn)生了一個(gè)種子,并通過(guò)CAS自旋方式保證,每次獲取的種子不一樣,從而保證每次new Random()獲取的隨機(jī)序列不一致。

nextInt() 方法:獲取 int 隨機(jī)數(shù)

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

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

從代碼中我們可以發(fā)現(xiàn),只要種子確定后,每次產(chǎn)生的數(shù),都是采用固定的算法進(jìn)行產(chǎn)生的,所以只要種子確定后,每次產(chǎn)生的序列就是固定的。

每次更新種子的時(shí)候是使用的CAS來(lái)更新的,如果高并發(fā)的環(huán)境下,性能是個(gè)問(wèn)題。

安全性問(wèn)題

試想下,如果這是一個(gè)搖獎(jiǎng)平臺(tái),只要種子確定后,每次產(chǎn)生的序列都一樣。這樣就可利用這個(gè)漏洞來(lái)預(yù)測(cè)下一次開(kāi)獎(jiǎng)的號(hào)碼,這樣容易被一些人鉆空子。

jdk建議大家盡量要使用 SecureRandom 來(lái)實(shí)現(xiàn)隨機(jī)數(shù)的生成。

SecureRandom

SecureRandom是強(qiáng)隨機(jī)數(shù)生成器,主要應(yīng)用的場(chǎng)景為:用于安全目的的數(shù)據(jù)數(shù),例如生成秘鑰或者會(huì)話標(biāo)示(session ID),在上文《偽隨機(jī)數(shù)安全性》中,已經(jīng)給大家揭露了弱隨機(jī)數(shù)生成器的安全問(wèn)題,而使用SecureRandom這樣的強(qiáng)隨機(jī)數(shù)生成器將會(huì)極大的降低出問(wèn)題的風(fēng)險(xiǎn)。

產(chǎn)生高強(qiáng)度的隨機(jī)數(shù),有兩個(gè)重要的因素:種子和算法。算法是可以有很多的,通常如何選擇種子是非常關(guān)鍵的因素。 如Random,它的種子是System.currentTimeMillis(),所以它的隨機(jī)數(shù)都是可預(yù)測(cè)的, 是弱偽隨機(jī)數(shù)。
強(qiáng)偽隨機(jī)數(shù)的生成思路:收集計(jì)算機(jī)的各種信息,鍵盤輸入時(shí)間,內(nèi)存使用狀態(tài),硬盤空閑空間,IO延時(shí),進(jìn)程數(shù)量,線程數(shù)量等信息,CPU時(shí)鐘,來(lái)得到一個(gè)近似隨機(jī)的種子,主要是達(dá)到不可預(yù)測(cè)性。

說(shuō)的簡(jiǎn)單點(diǎn)就是,使用加密算法生成很長(zhǎng)的一個(gè)隨機(jī)種子,讓你無(wú)法猜測(cè)出種子,也就無(wú)法推導(dǎo)出隨機(jī)序列數(shù)。

Random性能問(wèn)題

從 Random 源碼中我們發(fā)現(xiàn),每次獲取隨機(jī)數(shù)的時(shí)候都是使用CAS的方式進(jìn)行更新種子的值。這樣在高并發(fā)的環(huán)境中會(huì)存在大量的CAS重試,導(dǎo)致性能下降。這時(shí)建議大家使用ThreadLocalRandom類來(lái)實(shí)現(xiàn)隨機(jī)數(shù)的生成。

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

Thread 類

Thread 類中有一個(gè) threadLocalRandomSeed 屬性。

ThreadLocalRandom 結(jié)構(gòu)

SEED 變量是 threadLocalRandomSeed 在 Thread 對(duì)象中的偏移量。

ThreadLocalRandom.nextSeed() 方法

從這個(gè)方法中,我們發(fā)現(xiàn),每個(gè)線程的種子值都存儲(chǔ)在Thread對(duì)象的threadLocalRandomSeed 屬性中。

結(jié)論

因?yàn)門hreadLocalRandom 中的種子存儲(chǔ)在Thread對(duì)象中,所以高并發(fā)獲取Random對(duì)象時(shí),不會(huì)使用CAS來(lái)保證每次獲取的值不一致。
每個(gè)線程維護(hù)一個(gè)它自己的種子,每個(gè)線程需要獲取隨機(jī)數(shù)的時(shí)候,從當(dāng)前的Thread對(duì)象中獲取當(dāng)前線程的種子,進(jìn)行獲取隨機(jī)數(shù),性能大大提高。

好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • JPA原生SQL(自定義SQL)分頁(yè)查詢邏輯詳解

    JPA原生SQL(自定義SQL)分頁(yè)查詢邏輯詳解

    這篇文章主要介紹了JPA原生SQL(自定義SQL)分頁(yè)查詢邏輯詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • springboot后端存儲(chǔ)富文本內(nèi)容的思路與步驟(含圖片內(nèi)容)

    springboot后端存儲(chǔ)富文本內(nèi)容的思路與步驟(含圖片內(nèi)容)

    在所有的編輯器中,大概最受歡迎的就是富文本編輯器和MarkDown編輯器了,下面這篇文章主要給大家介紹了關(guān)于springboot后端存儲(chǔ)富文本內(nèi)容的思路與步驟的相關(guān)資料,需要的朋友可以參考下
    2023-04-04
  • Java使用Mail構(gòu)建郵件功能的完整指南

    Java使用Mail構(gòu)建郵件功能的完整指南

    Java Mail API 是一個(gè)功能強(qiáng)大的工具,它可以幫助開(kāi)發(fā)者輕松實(shí)現(xiàn)郵件的發(fā)送與接收功能,本文將介紹如何使用 Java Mail 發(fā)送和接收郵件,希望對(duì)大家有所幫助
    2025-03-03
  • JAVA解析XML字符串簡(jiǎn)單方法代碼案例

    JAVA解析XML字符串簡(jiǎn)單方法代碼案例

    這篇文章主要介紹了JAVA解析XML字符串簡(jiǎn)單方法代碼案例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • spring boot 本地圖片不能加載(圖片路徑)的問(wèn)題及解決方法

    spring boot 本地圖片不能加載(圖片路徑)的問(wèn)題及解決方法

    這篇文章主要介紹了spring boot 本地圖片不能加載(圖片路徑)的問(wèn)題,解決的辦法其實(shí)很簡(jiǎn)單,只要寫一個(gè)配置文件,也就是圖片位置的轉(zhuǎn)化器,原理是虛擬一個(gè)在服務(wù)器上的文件夾,與本地圖片的位置進(jìn)行匹配。需要的朋友可以參考下
    2018-04-04
  • spring強(qiáng)行注入和引用實(shí)例解析

    spring強(qiáng)行注入和引用實(shí)例解析

    這篇文章主要介紹了spring強(qiáng)行注入和引用實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • java并查集算法帶你領(lǐng)略熱血江湖

    java并查集算法帶你領(lǐng)略熱血江湖

    這篇文章主要為大家介紹了java并查集算法,以大家熱愛(ài)的方式,帶你領(lǐng)略熱血江湖中的并查集算法,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2021-11-11
  • IDEA下因Lombok插件產(chǎn)生的Library source does not match the bytecode報(bào)錯(cuò)問(wèn)題及解決方法(親測(cè)可用)

    IDEA下因Lombok插件產(chǎn)生的Library source does not match the bytecode報(bào)

    這篇文章主要介紹了IDEA下因Lombok插件產(chǎn)生的Library source does not match the bytecode報(bào)錯(cuò)問(wèn)題及解決方法,親測(cè)試過(guò)好用,需要的朋友可以參考下
    2020-04-04
  • Kotlin內(nèi)存陷阱inline使用技巧示例詳解

    Kotlin內(nèi)存陷阱inline使用技巧示例詳解

    這篇文章主要為大家介紹了Kotlin內(nèi)存陷阱inline使用技巧示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • 如何實(shí)現(xiàn)自己的spring boot starter

    如何實(shí)現(xiàn)自己的spring boot starter

    這篇文章主要介紹了如何實(shí)現(xiàn)自己的spring boot starter,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08

最新評(píng)論

黄浦区| 宝鸡市| 祁东县| 亚东县| 临颍县| 化州市| 盐亭县| 汾阳市| 阿鲁科尔沁旗| 大竹县| 红河县| 万源市| 万盛区| 会同县| 沁阳市| 延津县| 汤原县| 灵台县| 思南县| 镇赉县| 津南区| 平远县| 泰安市| 澎湖县| 新田县| 交口县| 洛川县| 北票市| 南丹县| 育儿| 福州市| 白河县| 扎兰屯市| 扶风县| 长子县| 栾川县| 察雅县| 沂源县| 柳州市| 贵德县| 天祝|