Search code examples
javarandomdistributionuniform-distribution

One Random instance per thread, seeded by the original Random instance to attain reproducibility


I need to do 1000 calculations, each one based on a random number. The entire run needs to be reproducible.

In a single threaded environment, I just create random based on a seed and use that for each calculation:

Random random = new Random(37);
for (Calculation c : calculations) {
    c.doCalculation(r.nextInt());
}

In a multi threaded enviromnent, where I have 10 threads, I 'd have a seeded random seed the thread Random's:

Random initRandom = new Random(37);
for (List<Calculation> p : calculationPartitions) {
    final Random threadRandom = new Random(initRandom.nextLong());
    executorService.submit(() -> {
        for (Calculation c : p) {
            c.doCalculation(threadRandom.nextInt());
        }
    });
}
// Merge the calculation results back in the same order as the calculationPartitions
...

Is this a good idea? Is it still an evenly distributed random in general? The fact that each threadRandom is seeded by the initRandom, does it not break the uniform distribution?

For reproducible reasons, I cannot share 1 global random, as some threads might run faster than others in some runs, so they would not always call the global random in the same order (and the contention could cause performance degradation).


Solution

  • You will get an even distribution of numbers via Random, however the order that the each list of Calculation objects in your list will run is not guaranteed so if these then pass the result to a shared list the order may vary over runs.