当前位置:首页 > Java技术 > Java随机数中的陷阱

Java随机数中的陷阱

2022年11月07日 23:05:37Java技术18

点击蓝色“程序猿DD”关注我

回复“资源”获取独家整理的学习资料!

Java随机数中的陷阱 _ JavaClub全栈架构师技术笔记

作者 | 码农小胖哥

来源 | 公众号「码农小胖哥」
Java随机数中的陷阱 _ JavaClub全栈架构师技术笔记

前言

随机数我们应该不陌生,业务中我们用它来生成验证码,或者对重复性要求不高的id,甚至我们还用它在年会上搞抽奖。今天我们来探讨一下这个东西。如果使用不当会引发一系列问题。

Java中的随机数

我们需要在Java中随机生成一个数字。java开发中我们通常使用java.util.Random来搞,它提供了一种伪随机的生成机制。Jvm 通过传入的种子(seed)来确定生成随机数的区间,只要种子一样,获取的随机数的序列就是一致的。而且生成的结果都是可以预测的。是一种伪随机数的实现,而不是真正的随机数。来确定使用的但是有些用例直接使用可能会导致一些意想不到的问题。Random的一个普遍用法:

// Random 实例
Random random = new Random();
//调用 nextInt() 方法 此外还有nextDouble(), nextBoolean(), nextFloat(), ...
random.nextInt();

或者,我们可以使用java中的数学计算类:

Math.random();

Math类只包含一个Random实例来生成随机数:

public static double random() {

    Random rnd = randomNumberGenerator;

    if (rnd == null) {

      // 返回一个新的Random实例

    rnd = initRNG();

   }

    return rnd.nextDouble();

    }

java.util.Random的用法是线程安全的。但是,在不同线程上并发使用相同的Random实例可能会导致争用,从而导致性能不佳。其原因是使用所谓的种子来生成随机数。种子是一个简单的数字,它为生成新的随机数提供了基础。我们来看看Random中的next方法:

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

}

首先,旧种子和新种子存储在两个辅助变量上。在这一点上,创造新种子的原则并不重要。要保存新种子,使用compareAndSet()方法将旧种子替换为下一个新种子,但这仅仅在旧种子对应于当前设置的种子的条件下才会触发。如果此时的值由并发线程操纵,则该方法返回false,这意味着旧值与例外值不匹配。因为是循环内进行的操作,那么会发生自旋,直到变量与例外值匹配。这可能会导致性能不佳和线程竞争。

多线程下的随机数

如果更多线程主动生成具有相同Random的实例的新随机数,则上述情况发生的概率越高。对于生成许多(非常多)随机数的程序,不建议使用这种方式。在这种情况下,您应该使用ThreadLocalRandom,它在1.7版本中添加到Java中。ThreadLocalRandom扩展了Random并添加选项以限制其使用到相应的线程实例。为此,ThreadLocalRandom的实例保存在相应线程的内部映射中,并通过调用current()来返回对应的Random。

安全的随机数

通过对Random 的一些分析我们可以知道Random事实上是伪随机,是可以推导出规律的,而且依赖种子(seed)。如果我们搞抽奖或者其他一些对随机数敏感的场景时,用Random就不合适了,容易被人钻空子。JDK提供了SecureRandom来解决这个事情。

SecureRandom是强随机数生成器,它可以产生高强度的随机数,产生高强度的随机数依赖两个重要的因素:种子和算法。算法是可以有很多的,通常如何选择种子是非常关键的因素。如Random,它的种子是System.currentTimeMillis(),所以它的随机数都是可预测的, 是弱伪随机数。强伪随机数的生成思路:收集计算机的各种信息,键盘输入时间,内存使用状态,硬盘空闲空间,IO延时,进程数量,线程数量等信息,CPU时钟,来得到一个近似随机的种子,主要是达到不可预测性。说的更通俗就是,使用加密算法生成很长的一个随机种子,让你无法猜测出种子,也就无法推导出随机序列数。

总结

今天我们探讨了业务中经常使用的随机数的一些机制和一些场景下的一些陷阱,希望你在使用随机数的时候能避免这种陷阱。

最后,欢迎大家在留言区分享下您的随机数生成方法。

本文通过OpenWrite的免费Markdown转换工具发布

-END-

留言交流不过瘾

关注我,回复“加群”加入各种主题讨论群

Java随机数中的陷阱 _ JavaClub全栈架构师技术笔记

Java随机数中的陷阱 _ JavaClub全栈架构师技术笔记

朕已阅 Java随机数中的陷阱 _ JavaClub全栈架构师技术笔记

作者:程序猿DD_
来源链接:https://blog.csdn.net/j3T9Z7H/article/details/102380564

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。


本文链接:https://www.javaclub.cn/java/68387.html

分享给朋友:

“Java随机数中的陷阱” 的相关文章

两年前写的Java基础总结书

两年前写的Java基础总结书

想法衍生 两年前的我,突发奇想,把自己学的Java基础进行规范化的整理,因为自己的文档编辑能力有限,所以写的排版不是很好,参照图书排版的形式,将书籍进行整理,可以供学习Java基础的朋友参考,由于时间有限,可能也会有问题,请指出。下载地址在最后 截图如下:...

深入理解 Java 并发锁

深入理解 Java 并发锁

📦 本文以及示例源码已归档在 javacore 一、并发锁简介 确保线程安全最常见的做法是利用锁机制(Lock、sychronized)来对共享数据做互斥同步,这样在同一个时刻,只有一个线程可以执行某个方法或者某个代码块,那么操作必然是原子性的,线程安全的...

JAVA的JDK环境变量的配置JAVA

JAVA的JDK环境变量的配置JAVA

首先要在官网下载java 官网:http://www.oracle.com/technetwork/java/javase/downloads/ 到这个界面 选择我接受 记住该地址 最好的办法新建记事本,然后按ctrl+s保存 java环境变量的...

Java 基础:hashCode方法

Java 基础:hashCode方法

Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket 一、前言     泥瓦匠最近被项目搞的天昏地暗。发现有些要给自己一些目标,关于技术的目标: 专注...

Java IO 之 OutputStream源码

Writer      :BYSocket(泥沙砖瓦浆木匠) 微         博:BYSocket 豆  ...

Java 容器 & 泛型:二、ArrayList 、LinkedList和Vector比较

Java 容器 & 泛型:二、ArrayList 、LinkedList和Vector比较

Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket 继续上一篇的容器文章认识容器,泥瓦匠慢慢带你们走进List的容器解说。今天泥瓦匠想说说 ArrayList 、LinkedList和Vector比较。...

图解 Java IO : 二、FilenameFilter源码

图解 Java IO : 二、FilenameFilter源码

Writer      :BYSocket(泥沙砖瓦浆木匠) 微         博:BYSocket 豆  &...

[Java 泥水匠] Java Components 之二:算法篇之项目实践中的位运算符(有你不懂的哦)

[Java 泥水匠] Java Components 之二:算法篇之项目实践中的位运算符(有你不懂的哦)

作者:泥沙砖瓦浆木匠 网站:http://blog.csdn.net/jeffli1993 个人签名:打算起手不凡写出鸿篇巨作的人,往往坚持不了完成第一章节。 交流QQ群:【编程之美 365234583】http://qm.qq.com/cgi-bin/qm/qr?k=...

java提高篇(十六)

java提高篇(十六)

     Java的基本理念是“结构不佳的代码不能运行”!!!!!       大成若缺,其用不弊。       大...

Java 基础之详解 Java IO

Java 基础之详解 Java IO

Java IO 基本概念 Java IO:即 Java 输入 / 输出系统。 区分 Java 的输入和输出:把自己当成程序, 当你从外边读数据到自己这里就用输入(InputStream/Reader), 向外边写数据就用输出(OutputStream/Writer)。...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。