java - 随机数的分布

标签 java random uniform-distribution

我有两种代码选择:

选项 1

int myFunc() {
  return new Random().nextInt();
}

或者:

选项 2

private static final Random random = new Random();

int myFunc() {
  return random.nextInt();
}

我知道选项 2 更符合习惯。我想知道选项 1 的有效性。

选项 1 中,我只会使用给定种子生成的第一个数字。在 选项 2 中,我选择一个种子并使用该种子生成 n 个数字。 IIUC 对随机性的保证就在这个用例上。

因此,我的问题是,如果我多次调用选项 1,是否可以保证输出分布的均匀性?

最佳答案

快速代码:

// For occasional tasks that just need an average quality random number
ExecutorService threadPool = Executors.newCachedThreadPool();
threadPool.execute( () -> {
  ThreadLocalRandom.current().nextInt(); // Fast and unique!
} );


// For SecureRandom, high quality random number
final Random r = new SecureRandom();
ExecutorService threadPool = Executors.newCachedThreadPool();
threadPool.execute( () -> {
  r.nextInt(); // sun.security.provider.NativePRNG uses singleton.  Can't dodge contention.
} );


// Apache Common Math - Mersenne Twister - decent and non-singleton
int cpu = Runtime.getRuntime().availableProcessors();
ExecutorService executor = Executors.newFixedThreadPool( cpu );
Map<Thread, RandomGenerator> random = new WeakHashMap<>( cpu, 1.0f );

executor.execute( ()-> {
   RandomGenerator r;
   synchronized ( random ) { // Get or create generator.
      r = random.get( Thread.currentThread() );
      if ( r == null ) random.put( Thread.currentThread(), r = new MersenneTwister() );
   }
   r.nextInt( 1000 );
} );

解释:

  1. 相同种子的两个随机将产生相同的数字。
    1. 因此我们将重点关注是否可以保证不同的种子。
  2. 理论上,每个线程中的new Random()并不能保证不同的seed。

    1. 新随机由 nanoTime 和一个“唯一”数字作为种子。
    2. 不能保证该数字是唯一的,因为它的计算是不同步的。
    3. 至于 nanoTime,它保证“至少与 currentTimeMillis 一样好”
    4. currentTimeMillis 不保证任何东西,可以是 pretty coarse
    5. 在现实生活中,这两个时间仅在 old linux systems and Win 98 上相同。
  3. 在实践中,每个线程中的 new Random() 基本上总是得到不同的种子。

    1. 创建线程是昂贵的。我的每 50,000 纳秒创建 1 个。那是 not slow
    2. 50µs 远高于 nanoTime 最高达 a few ten ns 的常见粒度。
    3. 唯一数计算(1.2)也很快,所以得到相同的数字是非常罕见的。
    4. 使用 Executors 创建一个 thread pool 以避免繁重的新线程开销。
  4. zapl suggested ThreadLocalRandom.current().nextInt()。好主意。

    1. 它不会创建新的 Random,但它也是一个 linear congruential generator
    2. 它为每个调用线程生成一个新的随机数作为该线程的种子。
    3. 它被构建为在多线程中非常快。 (见下面的注释。)
    4. 它由 SecureRandom 静态播种,产生质量更好的随机数。
  5. “均匀分布”只是 randomness tests 的一小部分。

    1. Randomsomewhat uniform ,它的结果可以是 predicted 给定两个值。
    2. SecureRandom 保证 this won't happens 。 (即加密强度高)
    3. 如果您在每个线程中创建一个新的 SecureRandom,就没有种子冲突的风险。
    4. 但目前它的来源无论如何都是single thread,没有并行生成。
    5. 对于支持多线程的良好 RNG,找到 external help,例如 Apache Common 的 MT

Note: Implementation details deduced from Java 8 source code. Future Java version may change; for example, ThreadLocalRandom is using sun.misc.Unsafe to store the seeds, which may be removed in Java 9 forcing ThreadLocalRandom to find a new way to work without contention.

关于java - 随机数的分布,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38242833/

相关文章:

c++ - 从随机数组输出最大最小值和平均值?

javascript - 单击时生成相同的随机数

python - 在球形体积内采样均匀分布的随机点

c - 均匀分布 : Bug or Paradox

java.lang.OutOfMemory错误: Java heap space during bytea download

java - 帕斯卡三角形的递归方法

javascript - JavaScript 环境中的安全 ID

java - 在 JPasswordField 上设置 PlaceHolder

java - 属性 "Any"已定义。使用 <jaxb :property> to resolve this conflict

python - random.uniform(0,1) 可以生成 0 或 1 吗?