13

I have a large distributed program across many different physical servers, each program spawns many threads, each thread use Math.random() in its operations to draw a piece from many common resource pools.

The goal is to utilize the pools evenly across all operations. Sometimes, it doesn't appear so random by looking at a snapshot on a resource pool to see which pieces it's getting at that instant (it might actually be, but it's hard to measure and find out for sure).

Is there something that's better than Math.random() and performs just as good (not much worse at least)?

Mysticial
  • 464,885
  • 45
  • 335
  • 332
user881480
  • 5,005
  • 6
  • 32
  • 31
  • +1 for a good question. Please let me know if you find an answer:) – Adel Boutros Apr 01 '12 at 10:47
  • Please have a look at the following link. http://www.coderanch.com/t/510167/java/java/Random-generator-failing – Chetter Hummin Apr 01 '12 at 10:51
  • Why not use some schedulers for the common resource pools? – Vitaly Olegovitch Apr 01 '12 at 10:52
  • 1
    @vitalik: any kind of controller/scheduler in front of resource pools will require coordinations and downgrade performance and spell disastrous complications in this case. – user881480 Apr 01 '12 at 11:05
  • Using a real RNG will you buy nothing here. I bet you observe just normal incidents. Report the number on which you think you observe suspicious behavior. If you throw a dice, you will sometimes observes 6-6-6 in a row. Don't use a RNG if you don't want random results. Or do you reinitialize every RNG with the time on every invocation? – user unknown Apr 01 '12 at 11:15
  • 1
    @user unknown: he's using Math.random(), so that's one error he's definitely not making. – Michael Borgwardt Apr 01 '12 at 11:24

4 Answers4

3

Math.random() is based on java.util.Random, which is based on a linear congruential generator. That means its randomness is not perfect, but good enough for most tasks, and it sounds like it should be sufficient for your task.

However, it sounds like you're using the double return value of Math.random() to choose between a fixed number of choices, which may further degrade the quality of the randomness. It would be better to use java.util.Random.nextInt() - just be sure to reuse the same Random object.

Sometimes, it doesn't appear so random by looking at a snapshot on a resource pool to see which pieces it's getting at that instant

Our brains are really good at spotting patterns in perfect randomness, so that means almost nothing.

Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
  • good point on Random.nextInt(), currently I simply multiply the random double by n and then round it to the nearest integer, is that very different from Random().nextInt()? – user881480 Apr 01 '12 at 11:30
  • @user881480: yes - Random produces integers, Math.random() does extra work to convert that to a double, only for you to convert it back to an int. This double conversion could reduce the quality of the randomness (not really certain, but might be). – Michael Borgwardt Apr 01 '12 at 11:36
1

Math.Random's algorithm is "random enough" for any platform. The mathematical model used for creating psuedo-random numbers is a good one. It depends on how many threads you use. For anything but a really large number of threads, this will not give you even distribution (the nature of random numbers), and then Math.random() will give you plenty of overhead.

Try a better option: make a resource pool class, which distributes them evenly - and then just keep it's critical section in the "distribute" method protected.

  • 1
    why would random numbers not give you an even distribution? in my case the number of threads per program is a few hundreds, but each thread performs many operations(1 per second, where each operation calls Math.random()). – user881480 Apr 01 '12 at 11:09
  • how would a resource pool class distribute the resources randomly? does it have to use Math.random()? – user881480 Apr 01 '12 at 11:10
  • You don't need to distribute it randomly, just create a simple class called Resources, a synchronized nextResource() method. That way you just keep going through them one by one, ensuring an even distribution. Also, using hundreds of threads creates more overhead than time saved except in a few very specific cases; you should limit the amount of threads to what your system can use efficiently. – user1304831 Apr 01 '12 at 12:21
  • @user881480 pseudo random number generators often don't equally represent the tails So, depending on how you set it up, you could have the first and last of the group underrepresented. – Jensen Buck Feb 21 '23 at 17:10
0

This thread can be usefull: How good is java.util.Random?

another alternatives:

  • generate a Random seed when init the random instance
  • if you using linux use /dev/urandom
Community
  • 1
  • 1
shem
  • 4,686
  • 2
  • 32
  • 43
  • I don't want to call external process from Java as it degrades performance, I'm running at a speed of 1 operation per second and there are many(hundreds of thousands or million) per day on a server. – user881480 Apr 01 '12 at 11:14
  • so the easiest thing that I can thing about is to create you own generator with longer period (as described in the link). you also have to remember that the chance to get 1,1,1,1,1 is the same chance as 45,1002,783,199,6 – shem Apr 01 '12 at 11:38
0

Per the javadoc Math.random() is just an easy way of using java.util.Random. That said it's just a pseudo random algorythm. An easy way of checking how random an algorythm realy is, is by drawing random points on x/y grid. You should not find any patterns.

To get real ramdom numbers you can use services like http://www.random.org . If this is to slow, maybe call it regularly to seed java.util.Random could get you closer to true random.

BetaRide
  • 16,207
  • 29
  • 99
  • 177