Java隨機數Random,ThreadLocalRandom,SecureRandom,Math.random()

阿里巴巴JAVA開發手冊提到:

. 【推薦】避免 Random 實例被多線程使用,雖然共享該實例是線程安全的,但會因競爭同一
seed 導致的性能下降。
說明:Random 實例包括 java.util.Random 的實例或者 Math.random()的方式。
正例:在 JDK7 之後,可以直接使用 API ThreadLocalRandom,而在 JDK7 之前,需要編碼保
證每個線程持有一個實例。

參考Java中的隨機數生成器:Random,ThreadLocalRandom,SecureRandomJava 隨機數 Random VS SecureRandom 以及 Java中生成隨機數Random、ThreadLocalRandom、SecureRandom、Math.random()的博客。

爲什麼多線程競爭下,Random實例會因爲競爭導致性能下降?

因爲Random在生成隨機數的時候使用了CAS。


如何使用呢?

Math.random():

它就是一個方法,生成0~1之間的隨機數double,也是使用到了Random類。

Random:

Random random = new Random();
Random random = new Random(10);//seed爲10

ThreadLocalRandom:

   
/** The common ThreadLocalRandom */
    static final ThreadLocalRandom instance = new ThreadLocalRandom();
//instance是在java.util.concurrent.ThreadLocalRandom類中的屬性 ,
//這也就說明了全局只有一個instance實例,而我們的程序調用
//ThreadLocalRandom.current()只是給當前線程初始化了一個種子。
//每個線程都有一個自己的種子,所以就不會發生多線程模式下的競爭。

每一個線程有一個獨立的隨機數生成器,用於併發產生隨機數,能夠解決多個線程發生的競爭爭奪。效率更高!

ThreadLocalRandom current = ThreadLocalRandom.current();

SecureRandom:

當需要安全性較高的時候用這個類,當然,只需要初始化一次實例就行了。

            //使用默認的算法- NativePRNG
            SecureRandom secureRandom = new SecureRandom();
            //使用SHA1PRNG算法
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            //使用SHA1PRNG算法,指定包名
            SecureRandom random1 = SecureRandom.getInstance("SHA1PRNG","SUN");
            //使用SHA1PRNG算法,指定provider(構造方法參數是隨便寫的)
            SecureRandom random2 = SecureRandom.getInstance("SHA1PRNG", new Provider("name", 1.1, "inf");

            

補充:

random.nextInt(10)生成一個0~9之間的數,不會生成10;

可以使用org.apache.commons.lang3包下面的RandomUtils.nextInt(3, 6)方法生成一個3~5之間的數,它使用到的是Random類。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章