如何在 Java
⚡ 智能摘要
随机数 Java 源自四个相关的标准库选项:Random 类、Math.random、ThreadLocalRandom 和 SecureRandom,每个选项都涵盖了实际应用中速度、线程安全性和加密强度的不同组合。

随机数字无处不在 Java从单元测试数据和掷骰子游戏到会话标记和洗牌后的牌组,本教程将解释如何在各种场景下生成随机数。 Java 使用标准库中的每个选项以及如何为特定任务选择合适的选项。
在中生成随机数 Java
此 Java 标准库提供了四种生成随机数的常用方法:
java.util.Random是通用类。它通过诸如以下方法生成布尔值、整数、长整型、浮点型和双精度浮点型值:nextInt,nextLong和nextDouble.Math.random是一个静态辅助函数,它使用共享的双精度浮点数返回一个介于 0.0(含)和 1.0(不含)之间的双精度浮点数。Random内部。ThreadLocalRandominjava.util.concurrent为每个线程分配自己的生成器,因此多个线程不会争用同一个实例。SecureRandominjava.security生成密码、会话标识符和密钥所需的加密强度高的伪随机数。
以下各节展示了如何使用每种方法生成十个随机数。
示例:使用以下方式生成随机数 Java 随机类
第一个例子使用 java.util.Random 生成十个介于 0 到 99 之间的整数(包含 0 和 99):
import java.util.Random; public class RandomNumbers { public static void main(String[] args) { Random objGenerator = new Random(); for (int iCount = 0; iCount < 10; iCount++) { int randomNumber = objGenerator.nextInt(100); System.out.println("Random No : " + randomNumber); } } }
输出:
Random No : 17 Random No : 57 Random No : 73 Random No : 48 Random No : 68 Random No : 86 Random No : 34 Random No : 97 Random No : 73 Random No : 18
一个实例 Random 创建方式 objGenerator。 该 nextInt(int bound) 该方法返回一个介于 0(含)和所提供的边界值(不含)之间的值,因此 nextInt(100) 返回值范围为 0 到 99。为了使序列可复现,请向构造函数传递一个种子,例如 10 ... new Random(42)同一个种子总是产生相同的序列,这在测试和模拟中很有用。
示例:使用 Java 数学随机数
要生成 0.0 到 1.0 范围内的 10 个随机值,请调用静态函数 Math.random 方法内部 循环这是在不创建生成器对象的情况下获取随机双精度浮点数的最快方法:
public class DemoRandom { public static void main(String[] args) { for (int xCount = 0; xCount < 10; xCount++) { System.out.println(Math.random()); } } }
输出:
0.46518450373334297 0.14859851177803485 0.5628391820492477 0.6323378498048606 0.1740198445692248 0.9140544122258946 0.9167350036262347 0.49251219841030147 0.7426056725722353 0.2039418871298877
在引擎盖下 Math.random 创建一个静态的 Random 首次使用和通话 nextDouble 确实如此。这个单一的共享生成器对于演示来说没问题,但在繁重的多线程负载下会成为瓶颈,接下来的章节将对此进行讨论。
生成自定义范围内的随机数
实际程序通常需要一个特定范围内的随机值,例如掷骰子需要一个 1 到 6 之间的整数,或者模拟需要一个 10.0 到 20.0 之间的双精度浮点数。两种模式几乎可以涵盖所有情况。
介于最小值和最大值之间的随机整数(包含最小值和最大值):
import java.util.Random; public class RangeDemo { public static void main(String[] args) { Random rnd = new Random(); int min = 1; int max = 6; // nextInt(max - min + 1) returns 0..(max-min), then shift by min int dice = rnd.nextInt(max - min + 1) + min; System.out.println("Dice roll : " + dice); } }
随机生成一个介于最小值和最大值之间的双精度浮点数:
double min = 10.0; double max = 20.0; double value = min + (max - min) * Math.random(); System.out.println("Value : " + value);
这两种模式的工作原理都是从生成器的原生范围内取一个值,将其缩放到目标范围的宽度,然后向上移动最小值。如果您正在使用…… Java 在 8 或更高版本中,可以通过较新的方法获得相同的结果。 ints, longs和 doubles 流方法 Random, 例如 rnd.ints(10, 1, 7).forEach(System.out::println) 掷十次骰子。
多线程的 ThreadLocalRandom Code
单一共享 Random 虽然线程安全,但在多线程竞争的情况下速度较慢,因为每个线程都必须在同一个内部种子上进行同步。 ThreadLocalRandom添加于 Java 7岁,住在 java.util.concurrent这样,每个线程都有自己的生成器,就不会出现锁争用。
import java.util.concurrent.ThreadLocalRandom; public class ThreadLocalDemo { public static void main(String[] args) { // random int in [1, 100] int i = ThreadLocalRandom.current().nextInt(1, 101); // random long in [1000, 5000] long l = ThreadLocalRandom.current().nextLong(1000L, 5001L); // random double in [0.0, 1.0) double d = ThreadLocalRandom.current().nextDouble(); System.out.println(i + " " + l + " " + d); } }
绝大部分储备使用 ThreadLocalRandom.current() 在工作线程、并行流和任何并发任务内部。请注意。 setSeed 投 UnsupportedOperationException因此,不支持使用种子数据来实现结果复现;如果您需要固定的种子数据,请使用普通模式。 Random.
SecureRandom 用于安全敏感型随机数生成器 Numbers
实例 Random 和 ThreadLocalRandom 并非加密安全的。攻击者只需少量输出样本即可重构内部状态并预测未来的值。对于密码、会话令牌、盐值和加密密钥,请使用 java.security.SecureRandom 相反,它从操作系统熵池中提取种子素材,并产生难以预测的值。
import java.security.SecureRandom; public class SecureDemo { public static void main(String[] args) { SecureRandom secure = new SecureRandom(); byte[] token = new byte[16]; secure.nextBytes(token); // 128-bit random token int otp = secure.nextInt(1_000_000); // 6-digit one-time code System.out.println("OTP : " + String.format("%06d", otp)); } }
SecureRandom 比 Random 因为它使用了更强大的算法和更丰富的种子数据。建议将其用于安全相关工作,而将速度更快的生成器用于游戏、模拟和测试数据。
