国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - 關(guān)于java.util.Random的實(shí)現(xiàn)原理詳解

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

2020-12-23 12:17jianshu Java教程

Java實(shí)用工具類庫中的類java.util.Random提供了產(chǎn)生各種類型隨機(jī)數(shù)的方法,下面這篇文章主要給大家介紹了關(guān)于java.util.Random實(shí)現(xiàn)原理的相關(guān)資料,文中通過示例代碼介紹的非常詳細(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)建,對每個(gè)實(shí)例完成同方法調(diào)用序列它們將生成和返回相同的數(shù)序列成同一方法調(diào)用序列,它們將生成和返回相同的數(shù)序列。

示例

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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é)果:

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

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

random 源碼分析

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

?
1
2
3
4
5
6
7
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)造方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
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;
}

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

無參構(gòu)造方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
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;
 }
}

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
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來更新的,如果高并發(fā)的環(huán)境下,性能是個(gè)問題。

安全性問題

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

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

securerandom

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

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

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

random性能問題

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

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

thread 類

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

thread 類中有一個(gè) threadlocalrandomseed 屬性。

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

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

seed 變量是 threadlocalrandomseed 在 thread 對象中的偏移量。

threadlocalrandom.nextseed() 方法

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

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

結(jié)論

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

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

原文鏈接:http://www.jianshu.com/p/ab0c15c6dd99

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 真实的国产乱xxxx在线 | 黄色成人在线视频 | 亚洲综合大片69999 | 九一视频在线观看 | 久久久国产视频 | 国产精品毛片在线 | 久久人人爽爽爽人久久久 | 国产一区二区精品在线观看 | 国产精品美女久久久av超清 | 久青草视频在线 | 亚洲电影在线观看 | 国产免费亚洲 | 久久精品国产99国产 | 国产成人一区二区啪在线观看 | а天堂中文最新一区二区三区 | 亚洲精品国产成人 | 精品视频在线播放 | 国产精品美乳一区二区免费 | 中文字幕一区二区三区精彩视频 | 久草福利| 欧美一级全黄 | 午夜欧美一区二区三区在线播放 | 中文字幕亚洲一区二区三区 | 激情综合网五月婷婷 | 欧美日韩亚洲视频 | 亚洲激情视频 | av在线免费观看网站 | www.xxx在线观看 | 蜜桃香蕉视频 | 午夜欧美精品久久久久 | 91综合在线 | 羞羞视频免费观看网站 | 99精品99| 欧洲一区| 国产日韩欧美一区二区 | 国产精品久久久久久久久久久久冷 | 五月天导航| 亚洲第一视频 | 自拍视频在线观看 | www.中文字幕.com | 韩日中文字幕 |