聶永的博客

          記錄工作/學習的點點滴滴。

          Fork/Join模式(JSR166y)手記之ThreadLocalRandom

          ThreadLocalRandom是一個可以獨立使用的、用于生成隨機數的類。繼承自Random,但性能超過Random,所謂“青出于藍而勝于藍”。其API所提供方法,不多,父類Random具有的,它也一樣具有。從表明看,是一個單例模式,其實不然:
          private static final ThreadLocal localRandom =
          new ThreadLocal() {
          protected ThreadLocalRandom initialValue() {
          return new ThreadLocalRandom();
          }
          };

          ThreadLocalRandom() {
          super();
          initialized = true;
          }


          public static ThreadLocalRandom current() {
          return localRandom.get();
          }
          采用ThreadLocal進行包裝的Random子類,每線程對應一個ThreadLocalRandom實例。測試代碼:
          @Test
          public void testInstance() {
          final ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
          final List randomList = new ArrayList();
          final Phaser barrier = new Phaser(1);

          new Thread() {
          @Override
          public void run() {
          randomList.add(ThreadLocalRandom.current());
          barrier.arrive();
          }
          }.start();

          barrier.awaitAdvance(barrier.getPhase());
          if (randomList.isEmpty()) {
          throw new NullPointerException();
          }

          Assert.assertTrue(threadLocalRandom != randomList.get(0));
          }
          這么一包裝,在性能上可以趕超Math.random(),不錯。
          @Test
          public void testSpeed() {
          final int MAX = 100000;
          ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();

          long start = System.nanoTime();
          for (int i = 0; i < MAX; i++) {
          threadLocalRandom.nextDouble();
          }
          long end = System.nanoTime() - start;
          System.out.println("use time1 : " + end);

          long start2 = System.nanoTime();
          for (int i = 0; i < MAX; i++) {
          Math.random();
          }
          long end2 = System.nanoTime() - start2;
          System.out.println("use time2 : " + end2);

          Assert.assertTrue(end2 > end);
          }
          非規范的性能測試,某次輸出結果:
          use time1 : 3878481
          use time2 : 8633080
          性能差別不止兩倍啊,哈哈。
          再看Math.random(),其生成也是依賴于Random類:
          private static Random randomNumberGenerator;

          private static synchronized void initRNG() {
          if (randomNumberGenerator == null)
          randomNumberGenerator = new Random();
          }

          public static double random() {
          if (randomNumberGenerator == null) initRNG();
          return randomNumberGenerator.nextDouble();
          }
          很奇怪,性能為什么差那么遠呢?可能個各自的next函數不同造成??匆幌翿andom中的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));
          }
          而ThreadLocalRandom的重寫版本為:
          protected int next(int bits) {  
          rnd = (rnd * multiplier + addend) & mask;
          return (int) (rnd >>> (48-bits));
          }
          相比ThreadLocalRandom的next(int bits)函數實現上更為簡練,不存在seed的CAS操作,并且少了很多的運算量。
          更為詳細的機制研讀,請閱讀參考資料中鏈接。
          另外,ThreadLocalRandom 也提供了易用的,兩個數字之間的隨機數生成方式。類似于:
          nextDouble(double least, double bound)
          nextInt(int least, int bound)
          nextLong(long least, long bound)
          隨機數的生成范圍為 最小值 <= 隨機數 < 最大值??梢园钚≈?,但不包含最大值。
          @Test
          public void testHowtoUse(){
          final ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
          final int MAX = 100;
          int result = threadLocalRandom.nextInt(0, 100);
          Assert.assertTrue(MAX > result);
          }
          嗯,還有,不支持setSeed方法。
          曾經JDK 7中,ThreadLocalRandom 存在隨機多個線程隨機數生成相同的bug,但最新版本中,已不存在,被修復了,可以放心使用。從現在開始,完全可以使用ThreadLocalRandom替代Random,尤其是在并發、并行、多任務等環境下,會比在多線程環境下使用公共共享的Random對象實例更為有效。
          代碼清單:

          參考資料:
          1. Java 7: How to write really fast Java code

          posted on 2012-02-04 11:29 nieyong 閱讀(1578) 評論(0)  編輯  收藏 所屬分類: Java

          公告

          所有文章皆為原創,若轉載請標明出處,謝謝~

          新浪微博,歡迎關注:

          導航

          <2012年2月>
          2930311234
          567891011
          12131415161718
          19202122232425
          26272829123
          45678910

          統計

          常用鏈接

          留言簿(58)

          隨筆分類(130)

          隨筆檔案(151)

          個人收藏

          最新隨筆

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 酒泉市| 辽宁省| 额济纳旗| 新龙县| 江孜县| 绵阳市| 治县。| 女性| 会泽县| 满洲里市| 泸州市| 阿荣旗| 九江县| 平安县| 钦州市| 玉树县| 葫芦岛市| 麻城市| 大港区| 普陀区| 吴桥县| 阳原县| 大安市| 东光县| 仲巴县| 兴海县| 唐河县| 平原县| 吉林省| 元氏县| 石渠县| 龙井市| 灵寿县| 临澧县| 霍林郭勒市| 观塘区| 临沂市| 紫金县| 伊宁市| 河源市| 临沧市|