private static final ThreadLocallocalRandom = 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 ListrandomList = 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)); }
@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
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函數不一樣形成。看一下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)); }而ThreadLocalRandom的重寫版本爲:
protected int next(int bits) { rnd = (rnd * multiplier + addend) & mask; return (int) (rnd >>> (48-bits)); }相比ThreadLocalRandom的next(int bits)函數實現上更爲簡練,不存在seed的CAS操做,而且少了不少的運算量。
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); }
代碼清單: java
package com.learn.jsry166y.demo.random; import java.util.ArrayList; import java.util.List; import jsr166y.Phaser; import jsr166y.ThreadLocalRandom; import junit.framework.Assert; import org.junit.Test; /** * ThreadLocalRandom簡單測試 * @author yongboy * @time 2012-2-2 * @version 1.0 */ public class RandomTest { @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); } // 判斷兩個線程之間所引用的ThreadLocalRandom實例是不同的 @Test public void testInstance() { final ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current(); final List<ThreadLocalRandom> randomList = new ArrayList<ThreadLocalRandom>(); // CountDownLatch的用法 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)); } @Test public void testHowtoUse(){ final ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current(); final int MAX = 100; int result = threadLocalRandom.nextInt(0, 100); Assert.assertTrue(MAX > result); } }