gpt4 book ai didi

JAVA中生成随机数RandomVSThreadLocalRandom性能比较

转载 作者:我是一只小鸟 更新时间:2022-12-15 06:31:12 29 4
gpt4 key购买 nike

前言

大家项目中如果有生成随机数的需求,我想大多都会选择使用Random来实现,它内部使用了CAS来实现。 实际上,JDK1.7之后,提供了另外一个生成随机数的类ThreadLocalRandom,那么他们二者之间的性能是怎么样的呢?

Random的使用

Random类是JDK提供的生成随机数的类, 这个类不是随机的,而是伪随机的。什么是伪随机呢? 伪随机是指生成的随机数是有一定规律的,这个规律出现的周期因伪随机算法的优劣而异。 一般来说,周期比较长,但可以预见。 我们可以通过以下代码简单地使用 Random:

Random中有很多方法。 这里我们就分析比较常见的 nextInt() 和 nextInt(int bound) 方法.

  • nextInt() 会计算int范围内的随机数,
  • nextInt(int bound) 会计算[0,bound) 之间的随机数,左闭右开。

实现原理

Random类的构造函数如下图所示:

  • 可以看到在构造方法中,根据当前时间 seed 生成了一个 AtomicLong 类型的 seed
                        
                          public int nextInt() {
    return next(32);
}

                        
                      
  • 这里面直接调用了 next() 方法,传入了32,这里的32是指Int的位数。
                        
                          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));
}

                        
                      
  • 这里会根据 seed 的当前值,通过一定的规则(伪随机)计算出下一个 seed ,然后进行CAS。 如果CAS失败,继续循环上述操作。 最后根据我们需要的位数返回。

小结:可以看出在 next(int bits) 方法中,对 AtomicLong 进行了CAS操作,如果失败则循环重试。 很多人一看到CAS,因为不需要加锁,第一时间就想到了高性能、高并发。 但是在这里,却成为了我们多线程 并发性能的瓶颈 。 可以想象,当我们有多个线程执行CAS时,只有一个线程一定会失败,其他的会继续循环执行CAS操作。 当并发线程较多时,性能就会下降.

ThreadLocalRandom的使用

JDK1.7之后,提供了一个新类 ThreadLocalRandom 来替代 Random .

实现原理

我们先来看下 current() 方法.

                        
                          public static ThreadLocalRandom current() {
    if (UNSAFE.getInt(Thread.currentThread(), PROBE) == 0)
        localInit();
    return instance;
}
static final void localInit() {
    int p = probeGenerator.addAndGet(PROBE_INCREMENT);
    int probe = (p == 0) ? 1 : p; // skip 0
    long seed = mix64(seeder.getAndAdd(SEEDER_INCREMENT));
    Thread t = Thread.currentThread();
    UNSAFE.putLong(t, SEED, seed);
    UNSAFE.putInt(t, PROBE, probe);
}

                        
                      
  • 如果没有初始化,先进行初始化,这里我们的 seed 不再是全局变量了。 我们的线程中有三个变量:
                        
                          /** The current seed for a ThreadLocalRandom */
@sun.misc.Contended("tlr")
long threadLocalRandomSeed;

/** Probe hash value; nonzero if threadLocalRandomSeed initialized */
@sun.misc.Contended("tlr")
int threadLocalRandomProbe;

/** Secondary seed isolated from public ThreadLocalRandom sequence */
@sun.misc.Contended("tlr")
int threadLocalRandomSecondarySeed;

                        
                      
  • threadLocalRandomSeed :这是我们用来控制随机数的种子。
  • threadLocalRandomProbe :这个就是ThreadLocalRandom,用来控制初始化。
  • threadLocalRandomSecondarySeed :这是二级种子。

关键代码如下:

                        
                          UNSAFE.putLong(t = Thread.currentThread(), SEED,r=UNSAFE.getLong(t, SEED) + GAMMA);

                        
                      

可以看出,由于每个线程都维护自己的 seed ,所以此时不需要 CAS ,直接进行put。 这里通过线程间的隔离来减少并发冲突,所以 ThreadLocalRandom 的性能非常高.

性能对比

通过基准工具JMH测试:

                        
                          @BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations=3, time = 5, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations=3,time = 5)
@Threads(4)
@Fork(1)
@State(Scope.Benchmark)
public class Myclass {
   Random random = new Random();
   ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();

   @Benchmark
   public int measureRandom(){
       return random.nextInt();
   }
   @Benchmark
   public int threadLocalmeasureRandom(){
       return threadLocalRandom.nextInt();
   }
	
}

                        
                      

运行结果如下图所示,最左边是并发线程的数量:

显而易见,无论线程数量是多少, ThreadLocalRandom 性能是远高于 Random .

总结

本文讲解了JDK中提供的两种生成随机数的方式,一个是JDK 1.0引入的 Random 类,另外一个是JDK1.7引入的 ThreadLocalRandom 类,由于底层的实现机制不同, ThreadLocalRandom 的性能是远高于 Random ,建议后面大家在技术选型的时候优先使用 ThreadLocalRandom .

如果本文对你有帮助的话,请留下一个赞吧 欢迎关注个人公众号——JAVA旭阳 更多学习资料请移步: 程序员成神之路 。

最后此篇关于JAVA中生成随机数RandomVSThreadLocalRandom性能比较的文章就讲到这里了,如果你想了解更多关于JAVA中生成随机数RandomVSThreadLocalRandom性能比较的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com