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); } }