The title pretty much summarizes it - we can create one instance of java.util.Random
(or SecureRandom
) and use it every time we need a random value or we can create a new instance every time on demand. Wondering which one is the preferred way and why?
To give some idea about the context: the random value is being generated inside an HTTP request handler, one per request, and I'm looking for the best combination for security and performance considering multi-threading.
It depends.
Creating a single instance is obviously simpler and should be the default behaviour. Both Random
and SecureRandom
are threadsafe, and will therefore work just fine. First do the simple and correct thing that works, then measure your performance against your expected peak contention / peak perf budget, and analyze the results.
Random
If you're using Random
and the single instance approach is too slow, consider using ThreadLocalRandom
if possible. The JavaDoc in Random
suggests its usage nicely:
Instances of
java.util.Random
are threadsafe. However, the concurrent use of the samejava.util.Random
instance across threads may encounter contention and consequent poor performance. Consider instead usingThreadLocalRandom
in multithreaded designs.
It will only create an instance for each thread accessing it. The creation cost of a Random
/ ThreadLocalRandom
instance is not insane, but it is higher than the creation of a "normal" object, so you should probably avoid creating a new instance for each incoming request. Creating one per thread is generally a nice sweet spot.
I would say that in modern applications with pooled threads, you should almost always use ThreadLocalRandom
instead of Random
- the randomness is the same, but the single-thread performance is much better.
SecureRandom
If you're using SecureRandom
, though, ThreadLocalRandom
is not an option. Again, do not guess, measure! Maybe using a single shared instance of a SecureRandom
will be good enough. Test with your expected peak contention, and if the secure random instance turns out to be a bottleneck, only then think about ways to improve the situation.
Creating a SecureRandom
instance is very costly, so you absolutely do not want to create one for each incoming request.
Depending on your application, a ThreadLocal<SecureRandom>
may be an option. Still, I think that's an overkill, and a scheme similar to the Striped
class (with X SecureRandom
instances created and accessed randomly to help prevent contention) may be preferred.