Java中生成随机数Random VS ThreadLocalRandom性能比较

网站建设4年前发布
37 0 0

大家项目中如果有生成随机数的需求,我想大多都会选择使用Random来实现,它内部使用了CAS来实现。实际上,JDK1.7之后,提供了另外一个生成随机数的类ThreadLocalRandom,那么他们二者之间的性能是怎么样的呢?,Random类是JDK提供的生成随机数的类, 这个类不是随机的,而是伪随机的。什么是伪随机呢?伪随机是指生成的随机数是有一定规律的,这个规律出现的周期因伪随机算法的优劣而异。一般来说,周期比较长,但可以预见。我们可以通过以下代码简单地使用 Random:,20230306153128c2ad2cc59298042b0c12781fe5dbe2c00ec6fb643,Random中有很多方法。这里我们就分析比较常见的nextInt()和nextInt(int bound)方法。,实现原理,Random类的构造函数如下图所示:,20230306153211b15fb512992002572f3395d38ff23de4f0c469294,这里面直接调用了next()方法,传入了32,这里的32是指Int的位数。,这里会根据seed的当前值,通过一定的规则(伪随机)计算出下一个seed,然后进行CAS。如果CAS失败,继续循环上述操作。最后根据我们需要的位数返回。,小结:可以看出在next(int bits)​方法中,对AtomicLong进行了CAS操作,如果失败则循环重试。很多人一看到CAS,因为不需要加锁,第一时间就想到了高性能、高并发。但是在这里,却成为了我们多线程并发性能的瓶颈。可以想象,当我们有多个线程执行CAS时,只有一个线程一定会失败,其他的会继续循环执行CAS操作。当并发线程较多时,性能就会下降。,JDK1.7之后,提供了一个新类ThreadLocalRandom​来替代Random。,2023030615312974f520039a71c515a021327949c79e3c0daeb1906,实现原理,我们先来看下current()方法。,如果没有初始化,先进行初始化,这里我们的seed不再是全局变量了。我们的线程中有三个变量:,关键代码如下:,可以看出,由于每个线程都维护自己的seed​,所以此时不需要CAS​,直接进行put。这里通过线程间的隔离来减少并发冲突,所以ThreadLocalRandom的性能非常高。,通过基准工具JMH测试:,运行结果如下图所示,最左边是并发线程的数量:,20230306153129387c8f7649a11c42ea3041cfc94b5731d0aa48337,20230306153211e9586176276eb80b70f699b536091e5fdddfda446,显而易见,无论线程数量是多少,ThreadLocalRandom​性能是远高于Random。,本文讲解了JDK中提供的两种生成随机数的方式,一个是JDK 1.0引入的Random​类,另外一个是JDK1.7引入的ThreadLocalRandom​类,由于底层的实现机制不同,ThreadLocalRandom​的性能是远高于Random​,建议后面大家在技术选型的时候优先使用ThreadLocalRandom。

© 版权声明

相关文章