java不同版本在多線程中使用隨機(jī)數(shù)生成器的實(shí)現(xiàn)
如何在多線程中使用隨機(jī)數(shù)生成器(Random)
避免 Random 實(shí)例被多線程使用,雖然共享該實(shí)例是線程安全的,但會(huì)因競(jìng)爭(zhēng)同一
seed 導(dǎo)致的性能下降。
說(shuō)明:Random 實(shí)例包括 java.util.Random 的實(shí)例或者 Math.random()的方式。
正例:在 JDK7 之后,可以直接使用 API ThreadLocalRandom,而在 JDK7 之前,需要編碼保證每個(gè)線程持有一個(gè)實(shí)例
具體來(lái)說(shuō):
- 避免多線程共享 Random 實(shí)例:雖然在多個(gè)線程之間共享 Random 實(shí)例是線程安全的,但會(huì)因?yàn)槎鄠€(gè)線程競(jìng)爭(zhēng)同一個(gè)種子(seed)而導(dǎo)致性能下降。因此,應(yīng)該盡量避免多個(gè)線程共享同一個(gè) Random 實(shí)例。
- 推薦使用 ThreadLocalRandom:在 JDK7 之后,推薦使用 ThreadLocalRandom 作為生成隨機(jī)數(shù)的方式。ThreadLocalRandom 是 Java 中的一個(gè)線程安全的隨機(jī)數(shù)生成器,它使用了不同的種子(seed)來(lái)生成隨機(jī)數(shù),避免了多個(gè)線程競(jìng)爭(zhēng)同一個(gè)種子導(dǎo)致性能下降的問(wèn)題。
- 在 JDK7 之前,需要保證每個(gè)線程持有一個(gè) Random 實(shí)例:如果使用的是 JDK7 之前的版本,不能使用 ThreadLocalRandom,而是需要保證每個(gè)線程持有一個(gè) Random 實(shí)例。這可以通過(guò)在每個(gè)線程中創(chuàng)建一個(gè)新的 Random 實(shí)例來(lái)實(shí)現(xiàn)。
綜上所述,對(duì)于多線程中的隨機(jī)數(shù)生成器,應(yīng)該盡量避免多個(gè)線程共享同一個(gè) Random 實(shí)例,而是使用 ThreadLocalRandom(JDK7之后)或者保證每個(gè)線程持有一個(gè) Random 實(shí)例(JDK7之前)。這樣可以避免因?yàn)槎鄠€(gè)線程競(jìng)爭(zhēng)同一個(gè)種子而導(dǎo)致性能下降的問(wèn)題。
Random 是通過(guò) seed 進(jìn)行同步的嗎?
JDK7 之前的 Random 在生成隨機(jī)數(shù)時(shí)是通過(guò) seed 進(jìn)行同步的。具體來(lái)說(shuō),Random 內(nèi)部有一個(gè)種子(seed)屬性,用于控制隨機(jī)數(shù)的生成。在生成隨機(jī)數(shù)時(shí),Random 使用線性同余法(LCG)根據(jù)種子計(jì)算出下一個(gè)種子,然后用這個(gè)新的種子生成隨機(jī)數(shù)。由于線性同余法的計(jì)算是基于種子進(jìn)行的,因此不同的種子會(huì)生成不同的隨機(jī)數(shù)序列。
在多線程環(huán)境下,如果多個(gè)線程同時(shí)訪問(wèn)同一個(gè) Random 實(shí)例,可能會(huì)導(dǎo)致多個(gè)線程競(jìng)爭(zhēng)同一個(gè)種子,從而出現(xiàn)性能下降的問(wèn)題。為了避免這個(gè)問(wèn)題,JDK7 之前的做法是通過(guò) synchronized 關(guān)鍵字對(duì) Random 的實(shí)例方法進(jìn)行同步,從而保證同一時(shí)刻只有一個(gè)線程可以訪問(wèn) Random 實(shí)例。但是這種做法會(huì)帶來(lái)一定的性能損失,因?yàn)樵诙嗑€程環(huán)境下,多個(gè)線程可能會(huì)因?yàn)楦?jìng)爭(zhēng)鎖而出現(xiàn)線程阻塞的情況。
因此,在 JDK7 之后,Java 推出了 ThreadLocalRandom,使用不同的種子來(lái)生成隨機(jī)數(shù),避免了多個(gè)線程競(jìng)爭(zhēng)同一個(gè)種子導(dǎo)致性能下降的問(wèn)題。
ThreadLocalRandom 生成隨機(jī)數(shù)的示例
import java.util.concurrent.ThreadLocalRandom; public class RandomDemo { ? ? public static void main(String[] args) { ? ? ? ? // 生成一個(gè)10到20之間的隨機(jī)整數(shù) ? ? ? ? int randomInt = ThreadLocalRandom.current().nextInt(10, 20); ? ? ? ? System.out.println(randomInt); ? ? ? ? // 生成一個(gè)0到1之間的隨機(jī)浮點(diǎn)數(shù) ? ? ? ? double randomDouble = ThreadLocalRandom.current().nextDouble(); ? ? ? ? System.out.println(randomDouble); ? ? ? ? // 生成一個(gè)100到200之間的隨機(jī)長(zhǎng)整數(shù) ? ? ? ? long randomLong = ThreadLocalRandom.current().nextLong(100, 200); ? ? ? ? System.out.println(randomLong); ? ? } }
在上面的示例中,我們通過(guò) ThreadLocalRandom.current() 獲取了當(dāng)前線程的 ThreadLocalRandom 實(shí)例,然后調(diào)用 nextInt、nextDouble 和 nextLong 等方法來(lái)生成隨機(jī)數(shù)。由于 ThreadLocalRandom 在不同線程中使用不同的種子來(lái)生成隨機(jī)數(shù),因此可以在多線程環(huán)境下使用。
到此這篇關(guān)于java不同版本在多線程中使用隨機(jī)數(shù)生成器的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)java 隨機(jī)數(shù)生成器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Eclipse 項(xiàng)目出現(xiàn)錯(cuò)誤(紅色嘆號(hào))解決方法
這篇文章主要介紹了Eclipse 項(xiàng)目出現(xiàn)錯(cuò)誤(紅色嘆號(hào))解決方法的相關(guān)資料,需要的朋友可以參考下2017-06-06Springboot中如何使用Redisson實(shí)現(xiàn)分布式鎖淺析
redisson是redis的java客戶端程序,國(guó)內(nèi)外很多公司都有在用,下面這篇文章主要給大家介紹了關(guān)于Springboot中如何使用Redisson實(shí)現(xiàn)分布式鎖的相關(guān)資料,需要的朋友可以參考下2021-10-10spring接口通過(guò)配置支持返回多種格式(xml,json,html,excel)
這篇文章主要給大家介紹了關(guān)于spring接口如何通過(guò)配置支持返回多種格式(xml,json,html,excel)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-12-12基于Spring5實(shí)現(xiàn)登錄注冊(cè)功能
這篇文章主要為大家詳細(xì)介紹了基于Spring5實(shí)現(xiàn)登錄注冊(cè)功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-09-09java8新特性-lambda表達(dá)式入門(mén)學(xué)習(xí)心得
這篇文章主要介紹了java8新特性-lambda表達(dá)式入門(mén)學(xué)習(xí)心得,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03淺談Java中實(shí)現(xiàn)深拷貝的兩種方式—clone() & Serialized
這篇文章主要介紹了Java中實(shí)現(xiàn)深拷貝的兩種方式—clone() & Serialized,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03java 下執(zhí)行mysql 批量插入的幾種方法及用時(shí)
java 下執(zhí)行mysql 批量插入的幾種方法及用時(shí),1000次插入方法的比較。2013-04-04