5

I am wondering under what circumstances that you would want to have a different seed for you random number generator. I see code somewhere that people create a Random object every time when needed, and also see people sometimes would have it as an instance variable that uses a single seed when the object is constructed. For example

// same seed
class A {
    private Random random;
    public A() { random = new Random(); }
    public int nextInt() { return random.nextInt(10000); }
    public double nextDouble() { return random.nextDouble(); }
}

versus

// different seed is used every time when you call the method
class B {
    public int nextInt() { return new Random().nextInt(10000); }
    public double nextDouble() { return new Random().nextDouble(); }
}

Please ignore this design for these two wrapper classes, just trying to show the difference.

f1sh
  • 11,489
  • 3
  • 25
  • 51
peter
  • 8,333
  • 17
  • 71
  • 94
  • I think the practice demonstrated by `class B` is just a mistake. It relies on the default seeding system to be of equal or better quality than the design of the PRNG, and that's not a safe assumption. If you see that arrangement in working code it would be appropriate to challenge it. – sh1 Oct 20 '16 at 22:01

3 Answers3

7

Two reasons to re-use a Random:

  • There is an overhead to creating a Random.

  • If code is fast, creating two different Random objects may end up using the same seed value, i.e. result will not be random. Even if code is not that fast, the different Random objects will be seeded with closely related seed values, reducing the randomness factor.

One reason for having multiple Random instances, though not a reason for creating a new one on every use. Quoting javadoc:

Instances of java.util.Random are threadsafe. However, the concurrent use of the same java.util.Random instance across threads may encounter contention and consequent poor performance. Consider instead using ThreadLocalRandom in multithreaded designs.

Even in a single-threaded application, using ThreadLocalRandom may be appropriate, as a simple means of obtaining a shared Random instance.

Andreas
  • 154,647
  • 11
  • 152
  • 247
  • So 99% of the time one single Random object should suffice, correct ? – peter Oct 19 '16 at 16:47
  • 1
    That is correct. As JohnBollinger mentions at the end of his answer, if you have two independent pieces of code that both needs random values, they may independently create their own instance of `Random`, for "organizational" simplicity. But other than that, a single-threaded application would rarely create multiple instances. – Andreas Oct 19 '16 at 16:47
  • I don't get the concurrent use that would lead to a consequent poor performance. Can you elaborate more on that please – peter Oct 19 '16 at 16:48
  • 1
    `Random` is thread-safe, but if too many threads try to get random values at the same time, you have a bottleneck, since `Random` can only generate one number at a time. If that happens, having a separate instance for each thread eliminates that bottleneck. – Andreas Oct 19 '16 at 16:52
  • Totally make sense. Thanks ! – peter Oct 19 '16 at 16:54
6

A pseudorandom number generator, such as java.util.Random, produces a deterministic sequence of numbers characterized by the initial seed. Such generators are crafted to produce sequences that appear to vary randomly and (usually) uniformly over the whole range of the PRNG.

You get the same sequence of numbers if you start with the same seed. That can be useful under some circumstances, but usually it is undesirable. In particular, your numbers will not have any appearance of randomness at all if you seed the PRNG with the same seed before generating each number.

But more subtle problems arise even if you seed the PRNG with different seeds before generating each number, including if you instantiate a new Random instead of reusing an existing one. In this case, you are not guaranteed to have the same range or distribution of results, and your results may exhibit correlations that they would not exhibit if you seeded only once.

So, when you say

I am wondering under what circumstances that you would want to have a different seed for you random number generator.

, about the only reason I can think of for wanting to change seed within one run of your program is that you have published enough draws from the PRNG that you are concerned about someone determining its implementation and internal state, and therefore being able to predict subsequent numbers. This would be a concern in practice only under rather special circumstances.

On the other hand, you generally do want to choose a different seed each time your program runs, else it will generate the same sequence of random numbers each time.

Generally, you should seed your PRNG once, and then use it as much as needed, without reseeding. It's not necessarily wrong to use multiple, independent PRNGs, but the reasons for doing so are mostly organizational (e.g. not having to worry about synchronization, not having to provide for injecting a Random instance) rather than functional.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
0

If you truly just want a single value, one time only, in an application, then any approach will yield similar enough results and it doesn't matter. If you're going to be pulling lots of random numbers, particularly the same algorithm running repeatedly, you will get better (not faster, but better) results by using the same Random object repeatedly.

The reason to have one vs. two objects is because you want distinctly different random number sequences (that, presumably, you seed differently and want to control differently). That's an application-dependent answer to determine if it matters.

For most uses you'll want the default seed, but it can be very useful to give your application the option of running with a pre-defined seed; for example:

  if (seedInputValueProvided)
    mRandom = new Random(seedInputValue);
  else
    mRandom = new Random();

Why do that? Testing. Development. If you create exactly one random object and reuse it, with a known seed value, you can re-run particular scenarios to test the same thing repeatedly (or re-create problems).

user1676075
  • 3,056
  • 1
  • 19
  • 26