Java生成随机数代码教程
知识点掌握了,还需要不断练习才能熟练运用。下面golang学习网给大家带来一个文章开发实战,手把手教大家学习《java代码如何生成随机数 java代码随机数功能的编写教程》,在实现功能的过程中也带大家重新温习相关知识点,温故而知新,回头看看说不定又有不一样的感悟!
Java中生成随机数的最佳实践是使用java.util.Random或ThreadLocalRandom,而非Math.random()。1. 对于单线程场景,使用Random类的nextInt(bound)方法配合公式min + random.nextInt(max - min + 1)可安全生成包含边界的指定范围整数,逻辑清晰且不易出错;2. 在多线程环境下,应优先使用ThreadLocalRandom.current().nextInt(min, max + 1),它为每个线程提供独立的随机数生成器,避免了线程竞争,性能更高且线程安全;3. 若涉及安全敏感场景如密钥生成,应使用SecureRandom以获取更高强度的伪随机数;4. Math.random()虽简便,但需额外计算和类型转换,易引入误差,不推荐用于整数范围生成。综上,根据场景选择合适的工具类是生成随机数的最佳实践,该方案完整覆盖了准确性、性能与安全性需求。
在Java中生成随机数,我们通常会用到java.util.Random
类或者Math.random()
方法。这两种方式各有侧重,但核心都是为了模拟不确定性,为程序带来一些“随机”的行为。对于大多数日常开发场景,Random
类提供了更灵活和功能丰富的选择,而Math.random()
则是一个快速获取0.0到1.0之间双精度浮点数的简便途径。
解决方案
在Java里搞定随机数,其实主要就两把刷子:java.util.Random
和 Math.random()
。我个人更倾向于用Random
,因为它功能更全,控制起来也方便些。
使用 java.util.Random
类
这是Java里生成随机数的主力。你需要先创建一个Random
对象实例。
import java.util.Random; public class RandomExample { public static void main(String[] args) { Random random = new Random(); // 创建一个Random实例 // 1. 生成一个int类型的随机数(范围是整个int的取值范围) int randomNumberInt = random.nextInt(); System.out.println("随机整数: " + randomNumberInt); // 2. 生成一个指定上限的int类型随机数(例如0到99之间,不包含100) int randomNumberBounded = random.nextInt(100); // 0到99 System.out.println("0到99的随机整数: " + randomNumberBounded); // 3. 生成一个double类型的随机数(0.0到1.0之间,不包含1.0) double randomNumberDouble = random.nextDouble(); System.out.println("随机浮点数 (0.0-1.0): " + randomNumberDouble); // 4. 生成一个boolean类型的随机数 boolean randomBoolean = random.nextBoolean(); System.out.println("随机布尔值: " + randomBoolean); // 5. 生成一个long类型的随机数 long randomNumberLong = random.nextLong(); System.out.println("随机长整数: " + randomNumberLong); // 6. 生成指定范围的随机数(例如1到100之间,包含1和100) // 公式:min + random.nextInt(max - min + 1) int min = 1; int max = 100; int randomNumberRange = min + random.nextInt(max - min + 1); System.out.println(min + "到" + max + "的随机整数: " + randomNumberRange); } }
Random
实例在默认情况下会使用当前时间作为种子(seed),这意味着每次程序运行时,如果你不指定种子,它会生成看起来不同的序列。但如果你用同一个种子初始化两个Random
实例,它们会生成相同的随机数序列,这在需要重现特定“随机”行为时很有用,比如测试。
使用 Math.random()
方法
这是一个静态方法,直接调用即可,不需要创建对象。它返回一个double
类型的伪随机数,范围是 0.0
到 1.0
之间,不包含 1.0
。
public class MathRandomExample { public static void main(String[] args) { double randomNumber = Math.random(); System.out.println("Math.random() 生成的随机数: " + randomNumber); // 如果想生成指定范围的int类型随机数,需要进行类型转换和数学运算 // 例如,生成1到100的随机整数: int min = 1; int max = 100; int randomNumberRange = (int)(Math.random() * (max - min + 1)) + min; System.out.println(min + "到" + max + "的随机整数 (通过Math.random()): " + randomNumberRange); } }
Math.random()
的底层实现其实也是依赖于java.util.Random
,所以它的“随机性”特性和Random
类是类似的。对于简单的随机浮点数需求,它非常方便。
Java中生成指定范围随机数的最佳实践是什么?
说实话,生成指定范围的随机数是日常开发里最常见的需求之一了。我见过不少人刚开始会有点迷糊,特别是边界条件,是包含还是不包含。我的经验是,对于整数范围,最稳妥、最直观的公式是:min + random.nextInt(max - min + 1)
。
这个公式的精髓在于max - min + 1
,它计算了min
到max
(包括min
和max
)之间整数的总个数。比如,如果你想生成1到100(都包含)的随机数,那么max - min + 1
就是100 - 1 + 1 = 100
。random.nextInt(100)
会生成0到99的随机数。然后,我们加上min
(也就是1),结果自然就是1到100了。
举个例子,假设你要模拟掷骰子,生成1到6的随机数:
Random random = new Random(); int diceRoll = 1 + random.nextInt(6); // 1到6 System.out.println("掷骰子结果: " + diceRoll);
为什么不直接用Math.random()
来生成整数范围呢?虽然可以,就像上面MathRandomExample
里展示的那样,但我觉得Random.nextInt(bound)
更清晰,意图表达更明确。Math.random()
需要额外的乘法、加法和类型转换,稍显繁琐,而且更容易在int
强制转换时出现意想不到的精度问题(虽然对于double
到int
通常不是大问题,但总归多了一步)。
总而言之,Random.nextInt(bound)
是我的首选,它直接、高效,而且不容易出错。
Java随机数生成是否真的“随机”?伪随机与真随机的区别?
这是一个挺有意思的问题,也常常被误解。简单来说,Java里我们用的Random
和Math.random()
生成的都不是真正的“随机数”,它们是“伪随机数”(Pseudo-Random Numbers)。
伪随机数,顾名思义,是看起来随机,但实际上是通过一个确定性算法生成的。这个算法从一个初始值(叫做“种子”或“seed”)开始,然后根据一系列复杂的数学运算,生成一个看似无规律的数字序列。如果你知道种子和算法,理论上你就能预测出接下来会生成什么数字。java.util.Random
默认使用系统当前时间作为种子,所以每次程序运行,种子不同,生成的序列也就不同,让你觉得它是随机的。但如果你手动指定一个种子,比如new Random(123L)
,那么每次用这个种子创建的Random
对象,都会生成一模一样的数字序列。这在调试和测试时非常有用,但在需要真正不可预测性的场合(比如加密),它就不够用了。
真随机数(True Random Numbers),则来源于物理世界的不可预测现象,比如大气噪声、放射性衰变、鼠标移动轨迹、硬盘读写时间等等。这些现象是真正随机的,无法通过算法预测。生成真随机数通常需要特殊的硬件设备。
那么,对于Java应用来说,伪随机数够用吗?对于大多数日常应用,比如游戏里的随机事件、模拟、抽奖(非加密级别)、数据采样等等,伪随机数是完全足够的,而且它们的生成速度非常快。
但如果你在做一些安全敏感的应用,比如生成加密密钥、会话ID、数字签名中的随机数等,那么伪随机数就不安全了。这时,你需要用到java.security.SecureRandom
类。SecureRandom
也是一个伪随机数生成器,但它会尽力收集更多的“熵”(entropy,简单理解就是随机性来源),比如操作系统的随机源,来生成更难以预测的序列。它的生成速度通常比Random
慢,因为它需要等待足够的熵被收集。
所以,核心区别就是:
- 伪随机数:算法生成,可预测(如果知道种子),速度快,适用于一般场景。
- 真随机数:物理现象生成,不可预测,需要特殊来源,适用于安全敏感场景。
Java的Random
和Math.random()
属于伪随机数,而SecureRandom
则是一个更安全的伪随机数生成器。
在并发环境下,Java随机数生成有哪些需要注意的问题?
并发环境下使用随机数,确实有一些坑需要注意。最主要的,java.util.Random
类本身是线程不安全的。这意味着,如果你在多个线程中共享同一个Random
实例,并且这些线程同时调用它的方法(比如nextInt()
),就可能导致数据竞争,产生不正确的结果,甚至出现性能瓶颈。我见过一些线上问题,就是因为多个线程争抢同一个Random
对象,导致随机数生成变得非常慢,甚至出现死锁。
为了解决这个问题,Java 7引入了一个非常棒的工具:java.util.concurrent.ThreadLocalRandom
。
ThreadLocalRandom
的优势
ThreadLocalRandom
是专门为多线程环境设计的。它的核心思想是:每个线程都维护一个自己的Random
实例。这样,线程之间就不会互相干扰,避免了竞争,从而提高了性能和并发性。你不需要手动创建和管理Random
实例,它会自动为你处理。
使用起来也非常简单:
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class ConcurrentRandomExample { public static void main(String[] args) throws InterruptedException { ExecutorService executor = Executors.newFixedThreadPool(5); // 创建一个线程池 for (int i = 0; i < 10; i++) { executor.submit(() -> { // 每个线程都通过ThreadLocalRandom.current()获取自己的随机数生成器 int randomNumber = ThreadLocalRandom.current().nextInt(1, 101); // 1到100 System.out.println(Thread.currentThread().getName() + " 生成了随机数: " + randomNumber); }); } executor.shutdown(); executor.awaitTermination(1, TimeUnit.MINUTES); System.out.println("所有线程任务完成。"); } }
注意看,这里我们没有像以前那样new Random()
,而是通过ThreadLocalRandom.current()
来获取。这个方法会返回当前线程的ThreadLocalRandom
实例。
ThreadLocalRandom
的优点:
- 性能提升:避免了多个线程对同一个
Random
对象的竞争和同步开销。 - 线程安全:天然的线程安全,无需额外同步措施。
- 使用方便:API与
Random
类似,学习成本低。
关于 SecureRandom
在并发中的考量
虽然SecureRandom
是用于加密安全的随机数,但它通常比Random
或ThreadLocalRandom
慢很多,因为它需要收集熵。如果在高并发的场景下频繁调用SecureRandom
,可能会成为性能瓶颈。如果你的应用确实需要在多线程环境下生成加密级别的随机数,并且对性能有要求,可能需要考虑一些策略,比如预先生成一批随机数缓存起来,或者使用专门的硬件随机数生成器。但对于绝大多数并发场景下的非加密随机数需求,ThreadLocalRandom
是毫无疑问的最佳选择。
今天带大家了解了的相关知识,希望对你有所帮助;关于文章的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~

- 上一篇
- Golangfmt库格式化输出详解

- 下一篇
- Java生成ZIP,Go解压兼容性详解
-
- 文章 · java教程 | 4小时前 |
- Java随机字母生成教程详解
- 354浏览 收藏
-
- 文章 · java教程 | 4小时前 |
- Java正则表达式高级用法解析
- 321浏览 收藏
-
- 文章 · java教程 | 4小时前 |
- Java生成ZIP,Go解压兼容性详解
- 280浏览 收藏
-
- 文章 · java教程 | 5小时前 |
- Java中List替换与排序技巧
- 122浏览 收藏
-
- 文章 · java教程 | 5小时前 | 线程安全 SimpleDateFormat DateTimeFormatter 时区处理 Java日期格式化
- Java日期格式化技巧与代码教程
- 302浏览 收藏
-
- 文章 · java教程 | 5小时前 |
- Java正则表达式验证技巧分享
- 159浏览 收藏
-
- 文章 · java教程 | 6小时前 |
- Elasticsearch混合搜索问题解决方法
- 470浏览 收藏
-
- 文章 · java教程 | 6小时前 |
- Java正则表达式实用技巧解析
- 355浏览 收藏
-
- 文章 · java教程 | 6小时前 |
- Java递归导致栈溢出原因及解决方法
- 176浏览 收藏
-
- 文章 · java教程 | 7小时前 |
- Java调用Rust方法全解析
- 274浏览 收藏
-
- 文章 · java教程 | 7小时前 |
- Java常用字符编码与文件处理技巧
- 455浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 511次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 498次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 千音漫语
- 千音漫语,北京熠声科技倾力打造的智能声音创作助手,提供AI配音、音视频翻译、语音识别、声音克隆等强大功能,助力有声书制作、视频创作、教育培训等领域,官网:https://qianyin123.com
- 333次使用
-
- MiniWork
- MiniWork是一款智能高效的AI工具平台,专为提升工作与学习效率而设计。整合文本处理、图像生成、营销策划及运营管理等多元AI工具,提供精准智能解决方案,让复杂工作简单高效。
- 341次使用
-
- NoCode
- NoCode (nocode.cn)是领先的无代码开发平台,通过拖放、AI对话等简单操作,助您快速创建各类应用、网站与管理系统。无需编程知识,轻松实现个人生活、商业经营、企业管理多场景需求,大幅降低开发门槛,高效低成本。
- 333次使用
-
- 达医智影
- 达医智影,阿里巴巴达摩院医疗AI创新力作。全球率先利用平扫CT实现“一扫多筛”,仅一次CT扫描即可高效识别多种癌症、急症及慢病,为疾病早期发现提供智能、精准的AI影像早筛解决方案。
- 336次使用
-
- 智慧芽Eureka
- 智慧芽Eureka,专为技术创新打造的AI Agent平台。深度理解专利、研发、生物医药、材料、科创等复杂场景,通过专家级AI Agent精准执行任务,智能化工作流解放70%生产力,让您专注核心创新。
- 360次使用
-
- 提升Java功能开发效率的有力工具:微服务架构
- 2023-10-06 501浏览
-
- 掌握Java海康SDK二次开发的必备技巧
- 2023-10-01 501浏览
-
- 如何使用java实现桶排序算法
- 2023-10-03 501浏览
-
- Java开发实战经验:如何优化开发逻辑
- 2023-10-31 501浏览
-
- 如何使用Java中的Math.max()方法比较两个数的大小?
- 2023-11-18 501浏览