tags:

views:

191

answers:

9

Hi All,

Say I have two classes like this:

class A{  
    private static Random random = new Random();  

    public A(){  
        // Do something.
    }

    public Integer methodGetsCalledQuiteOften(){
        return random.nextInt();
    }
}

class B{  
     private Random random;  

     public A(){  
         random = new Random();
         // Do something.
     }

     public Integer methodGetsCalledQuiteOften(){
         return random.nextInt();
     }
}

In a scenario where both of them get instantiated multiple times and both of these classes' instances' methodmethodGetsCalledQuiteOften gets called a lot, is there any real advantage/disadvantage (time, memory) in using a static variable that holds Random() in class A as opposed to creating a new Random() object in every single instance, like in class B?

EDIT: thanks everyone. The application is multithreaded & higher level of randomness is so I think I am going with static SecureRandom. If that will be a real speed factor after profiling I might choose something else.

+3  A: 

Real advantage/disadvantages depend on real code. In other words, it depends on how often a B is created compared to how often the method is called, etc. You should profile your application and see whether it makes a reasonable difference.

Will A be more performant than B? Certainly. But whether you'll ever notice depends on your usage. Will A use less memory than B? Certainly, but whether you care or not depends on how many instances of A/B you're keeping around.

Really the only other consideration is determinism. Since you don't specify the seed for the Random instance, I take it you don't care whether you can reproduce the sequence of numbers from the Random. But it's worth noting...if you have a shared Random, it will be much harder to guarantee a certain deterministic sequence of numbers for some instance of A than it is with one per instance as in B.

Mark Peters
+1  A: 

access to static resources is not thread safe. You might get weird/unpredictable results in a threaded environment.

hvgotcodes
Random class ensures synchronization internally: you can check the sources.
Nikita Rybak
*Unsynchronized* access to static resources *may* not be thread safe. It depends on the resource.
Richard Fearn
Access to instance fields isn't intrinsically thread safe either, and you might get weird/unpredictable results in a threaded environment.
Mark Peters
Isn't unpredictable what you want with a random?</joke>
Tom Hawtin - tackline
+1  A: 

Use a static variable when the instance isn't expected to change or when you want to share it between instances.

private final static int SOME_CONSTANT=1;

is an example.

public class USA {
    private final static Map statesOfTheUnion = new HashMap();
    // etc
}

could be another. In the latter case, we don't expect that the states will change from instance to instance. Thus is makes no sense for each instance to have its own copy.

Tony Ennis
Don't you mean to put `final` and `Collections.unmodifiableMap` in there?
Tom Hawtin - tackline
Great idea! ;-) This is just an example. :-) I left the `final` off to be more like the OP's code. I don't recall ever using `static` without `final`, however.
Tony Ennis
I added the `final`s. Good observation.
Tony Ennis
+1  A: 

Well, since Random class takes necessary steps to ensure thread-safety, I see no problem with making it static.

And since its state includes single AtomicLong object (8 bytes), it's no big waste of memory (unless you're planning on creating huge amount of B instances).

So, I'd say, there's little difference either way.

Nikita Rybak
Would be nice if they put that in the documentation for `Random`, instead of us relying on code inspection.
Mark Peters
The docs do say that `Random` is thread-safe, just not clearly: "The method next is implemented by class Random by atomically updating the seed ..."
erickson
@Mark Good point, more than few standard classes in Java have this problem.
Nikita Rybak
+3  A: 

If your program is single-threaded, your Random should be a class member (static). This is a bit more efficient. It is even more important when using a SecureRandom, which can take a relatively long time to seed initially.

If multiple threads will end up calling methodGetsCalledQuiteOften(), the issue is a bit more complicated. The class is thread-safe, but the overhead required to protect its state during concurrent changes might be comparable to making new, independent instances of Random.

I'd probably stick with a static member until I noticed a lot of contention among threads for the random number generator, which is likely to never happen.

erickson
The first `SecureRandom` will probably load a load of security infrastructure and take ages. However, after that it should relatively snappy, though not as fast as the old, predictable `java.util.Random`.
Tom Hawtin - tackline
A: 

In terms of time and memory I can't think of any big advantages (the static variable will be part of the class definition rather than on the heap). However static variables are useful when you know there will be accesses to the object from multiple places. hvgotcodes is right though that using static resources is not thread-safe. But if your only reading the static value then using threads for it is fine.

It'll save you from having to pass references to the initiated object (A or B) into other object in order to use random

Albinoswordfish
+1  A: 

If you are using java.util.Random, note that it is a linear congruential generator with well known problems related to correlation. To me, the real question is whether the application should choose from a single series or from several having different seeds.

trashgod
+1  A: 

Although instantiating Class A is substantialy (10x) faster than Class B, this only matters if you do this like 100.000 times a second.

About thread safety, it's my understanding that .nextInt() is based on .next() which should be thread safe. So multi threading should not give any problems here.

But more importantly, the behaviour of both classes might be different. Instances of Class A will give each a somewhat random sequence of numbers, but instances of Class B might each give the same sequence of 'random' numbers (this behavior can be different on different platforms!). The Javadoc spec states:

If two instances of Random are created with the same seed, and the same sequence of method calls is made for each, they will generate and return identical sequences of numbers.

Thus if randomness is important you might want to consider giving an unique seed to the Random constructor or better implement Random with the slower java.security.SecureRandom.

Kdeveloper
+3  A: 

Just say no to mutable static, m'kay.

It's atrocious design. The usual quoted consequence is that testability fails. It will be difficult to reproduce without reloading the class. Bad design is also bad for many other reasons. Just to mention one, classes should, by default, be thread-agnostic. Add a mutable static and you are thread-hostile - a bad place to be.

Creating a new instance every time seems wasteful. Although, of course, don't optimise prematurely (if you were optimising, you wouldn't be using java.util.Random). The initial see incrementing might also cause issues.

The best approach is to pass in an instance ("Parameterise from Above" or "using constructors correctly"). Then you can test, reproduce, mock, etc. You are efficient and can flip in a different implementation.

Tom Hawtin - tackline
+1 yep yep. _Add a mutable static and you are thread-hostile_
Tony Ennis