Java 随机数生成器

通过交互式代码示例学习如何在 Java 中生成随机数。探索 Random.nextInt()、SecureRandom、ThreadLocalRandom 和 Math.random() 的详细用法。

Java 代码编辑器

通过交互式代码示例学习如何在 Java 中生成随机数。探索 Random.nextInt()、SecureRandom、ThreadLocalRandom 和 Math.random() 的详细用法。

import java.util.Random;

public class RandomExample {
    public static void main(String[] args) {
        Random rand = new Random();
        int min = 1;
        int max = 100;
        int quantity = 5;

        System.out.println("Random numbers between " + min + " and " + max + ":");
        for (int i = 0; i < quantity; i++) {
            int num = rand.nextInt(max - min + 1) + min;
            System.out.print(num + " ");
        }
    }
}

输出

这是浏览器预览,不会执行 Java 或 C++;预览值不适合密码学用途。

预览示例

使用 java.util.Random 的基本随机数

使用 Random.nextInt() 生成指定范围内的随机整数。这是 Java 中通用随机数生成的最常用方法。

需要快速生成随机数?

试试我们的在线随机数生成器,无需编写代码即可获得即时结果。

打开随机数生成器

理解 Java 随机数生成

Java 提供了多种生成随机数的方法,每种都针对不同的用例进行了优化。java.util.Random 使用线性同余生成器(LCG)算法,SecureRandom 提供加密强度的随机数,ThreadLocalRandom 为并发应用提供线程安全的生成,Math.random() 提供生成随机 double 值的简单方法。

java.util.随机

java.util.Random 提供快速的伪随机数生成,适合模拟、游戏和通用编程任务。对于基本使用是线程安全的。

SecureRandom

java.security.SecureRandom 使用特定平台的算法(SHA1PRNG、NativePRNG)生成加密安全的随机数,用于安全应用。

线程本地随机

ThreadLocalRandom 专为多线程应用设计,提供高效的线程安全随机数生成,避免竞争和同步开销。

Math.random()

Math.random() 是一个简单的方法,返回 0.0 到 1.0 之间的 double 值。适合快速计算,但灵活性不如其他选项。

常见用例

游戏和模拟

在游戏循环中使用 Random.nextInt() 或 ThreadLocalRandom 生成随机骰子掷骰、抽卡、敌人生成和游戏事件。

安全和加密

使用 SecureRandom 创建安全密码、API 密钥、会话令牌和加密盐,以确保加密强度的随机性。

并发应用

在并行流和多线程应用中使用 ThreadLocalRandom 避免竞争并提高性能。

软件测试

创建随机测试数据、模糊测试输入和边缘情况,确保 Java 应用的健壮代码覆盖和错误检测。

Java 随机数生成如何工作

Java 的 java.util.Random 类使用线性同余生成器(LCG)算法和 48 位种子。它提供了一种生成伪随机数的简单方法,并且是线程同步的。

SecureRandom 类通过使用特定平台实现提供加密强度的随机数。在大多数系统上,它使用操作系统的熵源或硬件随机数生成器。

ThreadLocalRandom(Java 7 引入)专为多线程应用设计。它使用隔离到当前线程的随机数生成器,避免同步开销和竞争。

实用建议

🎯

选择正确的 API

简单情况使用 Random,安全相关使用 SecureRandom,并发应用使用 ThreadLocalRandom,快速原型使用 Math.random()。每种都有特定的用例。

🔒

安全场景始终使用 SecureRandom

切勿使用 Random 或 Math.random() 生成密码、令牌或加密操作。始终使用 SecureRandom 确保强随机性并避免可预测模式。

⚡

优化并发访问

在多线程应用中,ThreadLocalRandom 比同步 Random 对象快得多。在并行流和并发集合中使用它。

技术规范

算法

  • 线性同余生成器(Random 类)
  • SHA1PRNG 或 NativePRNG(SecureRandom)
  • ThreadLocalRandom(Java 7+,基于 Random)
  • 伪随机 double(Math.random())

性能特征

  • Math.random():简单 double 最快
  • ThreadLocalRandom:并发访问最佳
  • Random:通用良好,有同步开销
  • SecureRandom:由于熵收集而较慢

常见问题

涵盖了哪些 Java API?

java.util.Random、SecureRandom、ThreadLocalRandom 和 Math.random(),每个 API 都有一个重点示例。

我可以定制示例吗?

是的。在参数面板中设置最小值、最大值和数量,然后运行即可立即查看结果。

为了安全起见,我应该使用哪一个?

SecureRandom。其他 API 是可预测的,不得返回令牌、密钥或密码。

多线程代码怎么样?

ThreadLocalRandom 避免线程之间的争用,是并行流和线程池中的常用选择。

如何在 Java 中生成两个值之间的随机数?

调用 nextInt(bound) 可生成从 0 到 bound-1 的值,例如 nextInt(50) 会产生 0 到 49。若要自定义范围,可以加一个偏移量:nextInt(10) + 5 会产生 5 到 14。从 Java 17 开始,nextInt(origin, bound) 可以一次调用完成,其中 origin 包含在内,bound 不包含在内。

Math.random() 会返回 1 吗?

不会。Math.random() 返回一个 double 值,范围从 0.0(包含)到 1.0(不包含),因此可能出现 0.0 或 0.9999,但绝不会出现 1.0。它在内部委托给单个 java.util.Random 实例,所以在现代代码中直接调用 Random 的方法会更加清晰。

为什么每次运行程序时得到的随机数都相同?

使用固定种子创建的 Random(例如 new Random(42))总是重现完全相同的序列。去掉种子参数后,它会自动结合 System.nanoTime() 生成的唯一值来初始化种子。固定种子便于进行可重现的测试和调试,但不应出现在生产代码中。

如何从数组或列表中随机选取一个元素?

先生成一个索引,然后读取该位置的元素:列表使用 list.get(random.nextInt(list.size())),数组使用 array[random.nextInt(array.length)],因为 nextInt(n) 的范围是 0 到 n-1。另外,Collections.shuffle() 可以一次性随机打乱整个列表的顺序,因此单次洗牌中不会有元素重复。

参考资料与资源