java隨機數陷阱

      網友投稿 822 2025-03-31

      前言


      隨機數我們應該不陌生,業務中我們用它來生成驗證碼,或者對重復性要求不高的id,甚至我們還用它在年會上搞抽獎。今天我們來探討一下這個東西。如果使用不當會引發一系列問題。

      java隨機數的陷阱

      Java中的隨機數

      我們需要在Java中隨機生成一個數字。java開發中我們通常使用java.util.Random來搞,它提供了一種偽隨機的生成機制。Jvm 通過傳入的種子(seed)來確定生成隨機數的區間,只要種子一樣,獲取的隨機數的序列就是一致的。而且生成的結果都是可以預測的。是一種偽隨機數的實現,而不是真正的隨機數。來確定使用的但是有些用例直接使用可能會導致一些意想不到的問題。Random的一個普遍用法:

      // Random 實例 Random random = new Random(); //調用 nextInt() 方法 此外還有nextDouble(), nextBoolean(), nextFloat(), ... random.nextInt();

      1

      2

      3

      4

      或者,我們可以使用java中的數學計算類:

      Math.random();

      Math類只包含一個Random實例來生成隨機數:

      public static double random() { Random rnd = randomNumberGenerator; if (rnd == null) { // 返回一個新的Random實例 rnd = initRNG(); } return rnd.nextDouble(); }

      1

      2

      3

      4

      5

      6

      7

      8

      java.util.Random的用法是線程安全的。但是,在不同線程上并發使用相同的Random實例可能會導致爭用,從而導致性能不佳。其原因是使用所謂的種子來生成隨機數。種子是一個簡單的數字,它為生成新的隨機數提供了基礎。我們來看看Random中的next(int bits)方法:

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

      1

      2

      3

      4

      5

      6

      7

      8

      首先,舊種子和新種子存儲在兩個輔助變量上。在這一點上,創造新種子的原則并不重要。要保存新種子,使用compareAndSet()方法將舊種子替換為下一個新種子,但這僅僅在舊種子對應于當前設置的種子的條件下才會觸發。如果此時的值由并發線程操縱,則該方法返回false,這意味著舊值與例外值不匹配。因為是循環內進行的操作,那么會發生自旋,直到變量與例外值匹配。這可能會導致性能不佳和線程競爭。

      多線程下的隨機數

      如果更多線程主動生成具有相同Random的實例的新隨機數,則上述情況發生的概率越高。對于生成許多(非常多)隨機數的程序,不建議使用這種方式。在這種情況下,您應該使用ThreadLocalRandom,它在1.7版本中添加到Java中。ThreadLocalRandom擴展了Random并添加選項以限制其使用到相應的線程實例。為此,ThreadLocalRandom的實例保存在相應線程的內部映射中,并通過調用current()來返回對應的Random。使用方式如下:

      ThreadLocalRandom.current().nextInt()

      安全的隨機數

      通過對Random的一些分析我們可以知道Random事實上是偽隨機,是可以推導出規律的,而且依賴種子(seed)。如果我們搞抽獎或者其他一些對隨機數敏感的場景時,用Random就不合適了,容易被人鉆空子。JDK提供了SecureRandom來解決這個事情。SecureRandom是強隨機數生成器,它可以產生高強度的隨機數,產生高強度的隨機數依賴兩個重要的因素:種子和算法。算法是可以有很多的,通常如何選擇種子是非常關鍵的因素。 Random的種子是System.currentTimeMillis(),所以它的隨機數都是可預測的, 是弱偽隨機數。強偽隨機數的生成思路:收集計算機的各種信息,鍵盤輸入時間,內存使用狀態,硬盤空閑空間,IO延時,進程數量,線程數量等信息,CPU時鐘,來得到一個近似隨機的種子,主要是達到不可預測性。說的更通俗就是,使用加密算法生成很長的一個隨機種子,讓你無法猜測出種子,也就無法推導出隨機序列數。

      總結

      今天我們探討了業務中經常使用的隨機數的一些機制和一些場景下的一些陷阱,希望你在使用隨機數的時候能避免這種陷阱。

      Java 任務調度

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:Excel2007中設置表格密碼的操作方法(excel2007 設置密碼)
      下一篇:智能停車場管理系統多少錢一套
      相關文章
      亚洲av网址在线观看| 亚洲国产精品网站在线播放| 亚洲国产精品一区二区三区在线观看| 中文字幕专区在线亚洲| 国产成人精品日本亚洲语音| 亚洲精品自偷自拍无码| 亚洲国产精品久久久久秋霞影院| 老司机亚洲精品影院无码 | 亚洲av无码专区青青草原| 亚洲精品国产肉丝袜久久| 亚洲男人的天堂在线播放| 亚洲av无码一区二区三区网站| 亚洲中文久久精品无码| 亚洲精品V欧洲精品V日韩精品 | 亚洲美女自拍视频| 久久亚洲春色中文字幕久久久| 久久久久无码精品亚洲日韩| 亚洲国产精品无码久久一线| 亚洲精品无码久久一线| 亚洲AV无码成人专区片在线观看| 亚洲第一福利视频| 亚洲第一永久在线观看| 亚洲制服丝袜第一页| 亚洲七久久之综合七久久| 亚洲AV无码国产剧情| 亚洲国产一区二区三区| 久久影院亚洲一区| 久久精品7亚洲午夜a| 亚洲精品午夜久久久伊人| 亚洲xxxx18| 亚洲AV无码专区在线厂| 亚洲情a成黄在线观看| 亚洲精品无码av人在线观看 | 亚洲一区中文字幕久久| 亚洲欧洲综合在线| 亚洲熟妇自偷自拍另欧美| 老司机亚洲精品影院在线观看| 久久精品国产精品亚洲| 亚洲AV无码一区二区二三区入口| 91久久亚洲国产成人精品性色 | 亚洲第一男人天堂|