不知好几年前的一个问题:假设你希望产生位于0和某个上界之间的随机整数,你该怎么去做?时隔多年后又重新记起,转眼一看,她已经有了很大的发展。
几年前的写法突然翻出几年前写的东西,看到这个原始的写法,顿感漏洞百出。虽然这个写法目前都还感觉不错,但是有着三大缺陷。
一、如果n是一个比较小的2的乘方,经过一段相当短的周期之后,它产生的随机数序列将会重复,生成的效率低下。
二、如果n不是2的乘方,那么平均起来,有些数会比其他的数出现得更为频繁。
如果n比较大,这个缺点就会非常明显,如果将N我们暂定为100万,重复执行1万次,我们会发现它打印出来的数接近于666666。由random方法产生的数字有三分之二落在随机数取值范围的前半部分。随机值就变成不是随机值了。
调侃一句:说不定TX的抽奖就是这样的,我多年抽奖不中的原因貌似找到了。
三、在极少数情况下,它会失败,因为会返回一个落在指定范围之外的数。
正常的写法因为这个方法试图通过调用Math.abs,将rnd. nextInt()返回的值映射为一个非负整数。如果nextInt()返回Integer.MIN VALUE,那么Math.abs也会返回Integer.MIN_VALUE,假设n不是2的乘方,那么取模操作符(%)将返回一个负数。这几乎肯定会使程序失败,而且这种失败很难重现!
这种写法简单,并且完美地避免了最原始的上面的问题,但是这似乎还不够。
优秀的 ThreadLocalRandom从Java7开始,提供了一个全新的ThreadLocalRandom,就不应该再使用Random了。现在选择随机数生成器时,大多使用 ThreadLocalRandom。它会产生更高质量的随机数,并且速度非常快。我自己测试了一下,比Random快了3.6倍。但是对于ForkJoin Pool和并行Stream,则推荐使用SplittableRandom。
ThreadLocalRandom写法
SplittableRandom写法
不知道友友们,有没有好的建议和意见,觉得不错,点赞支持下,相互交流交流