Saturday, August 14, 2010

Trivial but important - Java Random Number

Summer 2010 in Bloomington is nearly end (I hope it ends sooner since it's freaking hot here). I've worked as a researcher on TeraGrid project for entire summer. My main task is to create a test library (program) to use against GRAM5 gateway which will be deployed on TeraGrid (soon). It is coded in Java and used for both scalability and reliability test. The problem comes up when I try to submit multiple jobs to GRAM5 gateway from multiple machines. If I start submission at the same time for all machines, program will get a connection reset from a server. I think it is caused by the fact that network router or server has a mechanism to prevent flooding.

At first, I use a simple solution which is delaying a job submission randomly in each machine using java.util.Random class. It worked fine up to around 50 machines then it started to get connection reset again. The situation becomes worse when I use 100 nodes, 90% of jobs fail. Therefore, I google around knowing in my mind that there must be something wrong about Random class. Finally, I found this site[1]. The important properties of Random class are
  • Random number is generated in deterministic way based on a given number called seed
  • Default constructor will use System.currentTimeMillis()as seed.
So, if we give the same seed number to Random class, it will generate a same sequence of random number. In my case, it's likely that each machines create a Random object at the same time, so they get the same seed. The solution is simple, we need to give a different seed on different machines. I use java.util.UUID to generate a unique ID across multiple machines (the odd is very low for different JVM to generate the same UUID) and create a seed from it. Here is my final code

Random random = new Random(UUID.randomUUID().hashCode());
int sleepTime = random.nextInt(120)
Thread.sleep(sleepTime * 1000l);

Resources:
[1] - http://java.about.com/od/javautil/a/randomnumbers.htm

2 comments:

Firzan said...

plz explain me why you used a


Thread.sleep(sleepTime * 1000L);

instead
Thread.sleep(sleepTime * 1000);

what is the use of L character???

Patanachai said...

A number followed by "l" in Java is a Long type (64bit).

I want to convert from int to long, so a * operation between sleeptime variable(int) and 1000l(long) will result in long (numeric promotion).

Although it seems unnecessary in small amount ,but be careful when dealing with time since Integer in Java is 32 bits = 2^31 (positive number).

So, it can hold only 2^31 / 24 / 60 / 60 / 1000 ~ 24 days.
That's why Thread.sleep method need Long as parameter.