JAVA基础之放弃使用Random

        随机是日常生活中经常遇到的非常有趣的东西,比如说抛硬币,他的不可预知性总是让我们特别着迷,在拿不定主意时,有些人就喜欢用抛硬币的方式来帮助我们做决定。体育领域也喜欢用喜欢用抛硬币的方式来猜先。随机数功能是Java非常非常基础的功能。早在1.0的版本就引入了Random类。

Random
        Random类的使用
public static void main(String[] args) {Random random = new Random();// 0-10的随机整数int randomResult = random.nextInt(10);System.out.println(randomResult);
}
        Random的实现原理

        Random通过一个种子(seed),进行简单的计算来生成随机数的,具体算法如下:

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

        其中multiplier,addend和mask是在类中写死的,这种算法叫线性同余算法(LCG)有兴趣的同学可以自己去了解一下,这里就不展开了。结论是算法会造成一种情况是相同的因子的相同生成次数会得到相同的数。

public static void main(String[] args) {Random random1 = new Random(1000L);Random random2 = new Random(1000L);for (int i = 0; i < 5; i++) {System.out.printf("%nrandom1的第%s次生成随机数" + random1.nextInt(100), i);System.out.printf("%nrandom2的第%s次生成随机数" + random2.nextInt(100), i);}
}

        得到结果

        由于Random使用LCG算法生成伪随机数,而且Random的随机数是可预测的会造成安全问题,所以我们需要一个安全的真随机数生成器:SecureRandom。 

SecureRandom

        内置两种随机数算法:SHA1PRNG和NativePRNG。也支持基于SPI机制对算法进行扩展。默认是NativePRNG算法。SecureRandom类会收集一些随机事件,比如鼠标点击、键盘敲击等,SecureRandom使用这些随机事件作为种子,使种子不再是可以预测的。

        ScureRandom类的使用
public static void main(String[] args) throws NoSuchAlgorithmException {// 使用默认算法:NativePRNG// SecureRandom random = new SecureRandom();// 指定算法:SHA1PRNGSecureRandom random = SecureRandom.getInstance("SHA1PRNG");int result = random.nextInt(10);System.out.println(result);
}

        Random的线程安全是通过AtomicLong的CAS操作保证的,java7版本发布了多线程情况下的性能优化版本的Random类:ThreadLocalRandom

ThreadLocalRandom

        ThreadLocalRandom有两项重要改动。

        第一项改动是,弃用AtomicLong,将种子seed改为普通的Long类型,避免了高竞争的情况下CAS的性能下降问题;

        第二项改动是,我们不需要再创建ThreadLocalRandom对象实例,构造函数已经设置成私有的了,可以通过ThreadLocalRandom.current()获取;

        ThreadLocalRandom类的使用
public static void main(String[] args) {for (int i = 0; i < 10; i++) {int result = ThreadLocalRandom.current().nextInt(10);System.out.println(result);}
}

        在学习时,也看了其他大佬的文章,看到了他们提到的错误用法,我在这里记录一下,避免你们实践的时候会遇到。

public class RandomTest {private static ThreadLocalRandom RANDOM = ThreadLocalRandom.current();public static void main(String[] args) {for (int i = 0; i < 10; i++) {new Player().start();}}private static class Player extends Thread {@Overridepublic void run() {System.out.println(getName() + ": " + RANDOM.nextInt(100));}}
}

输出结果

        这是为什么呢,实话实说我疑惑了一阵子,后来发现,所有的子线程都是在用main现场初始化的ThreadLocalRandom对象,没有经过初始化,子线程的SEED没有经过初始化就是0,大家的SEED都是相同的情况下,自然就会跟Random中落入相同的seed相同的次数获取的值都相同的陷阱中。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/61128.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

跳跃游戏 II——力扣45

文章目录 题目描述解法一 贪心题目描述 解法一 贪心 int jump(vector<int>& nums){in

Python-OpenCV中的图像处理-图像平滑

Python-OpenCV中的图像处理-图像平滑 图像平滑平均滤波高斯模糊中值模糊双边滤波 图像平滑 使用低通滤波器可以达到图像模糊的目的。这对与去除噪音很有帮助。其实就是去除图像中的高频成分&#xff08;比如&#xff1a;噪音&#xff0c;边界&#xff09;。所以边界也会被模糊…

Annotorious.js 入门教程:图片注释工具

theme: smartblue 本文简介 【今天我必须发一个封面&#xff01;放文末&#xff01;】 最近有工友问我前端怎么给图片做标注。使用 Fabric.js 或者 Konva.js 等库确实可以实现&#xff0c;但多少觉得有点大炮打蚊的感觉&#xff0c;好奇有没有专门做图片标注的工具呢&#xff1…

AI量化模型预测挑战赛 第二次学习笔记

有关竞赛信息以及基础baseline代码解读请看我的上一篇文章 AI量化模型预测——baseline学习笔记_寂ღ᭄秋࿐的博客-CSDN博客 在经过baseline进行详细的分析之后&#xff0c;接下来的方向肯定是奔着提分去的&#xff0c;下面我就从五个方面进行一一列出提分思路 提取更多的特征…

Java多线程(九)

目录 一、synchronized基本特点 二、synchronized加锁工作过程 2.1 无锁 2.2 偏向锁 2.3 轻量级锁 2.4 重量级锁 三、synchronized其他优化操作 3.1 锁消除 3.2 锁粗化 一、synchronized基本特点 开始是乐观锁&#xff0c;如果锁冲突频繁就会转换成悲观锁开始是轻量级锁&#x…

Kubernetes(K8s)从入门到精通系列之十:使用 kubeadm 创建一个高可用 etcd 集群

Kubernetes K8s从入门到精通系列之十&#xff1a;使用 kubeadm 创建一个高可用 etcd 集群 一、etcd高可用拓扑选项1.堆叠&#xff08;Stacked&#xff09;etcd 拓扑2.外部 etcd 拓扑 二、准备工作三、建立集群1.将 kubelet 配置为 etcd 的服务管理器。2.为 kubeadm 创建配置文件…

MySQL事务:ACID特性实现原理

事务是MySQL等关系型数据库区别于NoSQL的重要方面&#xff0c;是保证数据一致性的重要手段。本文将首先介绍MySQL事务相关的基础概念&#xff0c;然后介绍事务的ACID特性&#xff0c;并分析其实现原理。 MySQL博大精深&#xff0c;文章疏漏之处在所难免&#xff0c;欢迎批评指…

qt creater运行按钮灰色,问题记录

第一次安装还没运行就出了三个错误&#xff1a; 1.F:\wei\Qt\Tools\CMake_64\share\cmake-3.24\Modules\CMakeTestCXXCompiler.cmake:62: error: The C compiler "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/BIN/amd64/cl.exe" is not able to compil…

JVM 调优实例

点击下方关注我&#xff0c;然后右上角点击...“设为星标”&#xff0c;就能第一时间收到更新推送啦~~~ JVM提供了多种垃圾回收器&#xff0c;可以根据应用程序的需求选择最适合的垃圾回收器。例如&#xff0c;如果应用程序需要更快的响应时间&#xff0c;可以选择并行垃圾回收…

Unity 打造游戏攻击技能架构与设计

一、技能系统的设计 在 MOBA 游戏中&#xff0c;每个英雄角色都会有多个技能&#xff0c;这些技能可以分为普通攻击和技能攻击两种。普通攻击是英雄角色的基本攻击方式&#xff0c;而技能攻击则需要消耗一定的资源&#xff08;如蓝量&#xff09;才能使用。在设计技能系统时&a…

HoG特征笔记

简介 HoG&#xff08;Histogram of Oriented Gradient&#xff09;&#xff0c;方向梯度直方图。HoG特征是一种特征描述符。它通过计算和统计图像局部区域的梯度方向直方图来描述特征。 HoG基于的底层原理是图像中局部目标的表象和形状&#xff08;appearance and shape&#x…

公网环境Windows系统,远程桌面控制树莓派《内网穿透》

远程桌面控制树莓派&#xff0c;我们可以用xrdp协议来实现&#xff0c;它内部使用的是windows远程桌面的协议。我们只需要在树莓派上安装xrdp&#xff0c;就可以在同个局域网下远程桌面控制树莓派。 而如果需要在公网下远程桌面控制树莓派&#xff0c;可以通过cpolar内网穿透&a…