This question regards the implementation of ThreadLocalRandom
in OpenJDK version 1.8.0.
ThreadLocalRandom
provides a per-thread random number generator without the synchronization overhead imposed by Random. The most obvious implementation (IMO) would be something like this, which appears to preserve backward compatibility without much complexity:
public class ThreadLocalRandom extends Random {
private static final ThreadLocal<ThreadLocalRandom> tl =
ThreadLocal.withInitial(ThreadLocalRandom::new);
public static ThreadLocalRandom current() {
return tl.get();
}
// Random methods moved here without synchronization
// stream methods here
}
public class Random {
private ThreadLocalRandom delegate = new ThreadLocalRandom();
// methods synchronize and delegate for backward compatibility
}
However, the actual implementation is totally different and quite bizarre:
ThreadLocalRandom
duplicates some of the methods inRandom
verbatim and others with minor modifications; surely much of this code could have been reused.Thread
stores the seed and a probe variable used to initialize the `ThreadLocalRandom, violating encapsulation;ThreadLocalRandom
usesUnsafe
to access the variables inThread
, which I suppose is because the two classes are in different packages yet the state variables must be private inThread
-Unsafe
is only necessary because of the encapsulation violation;ThreadLocalRandom
stores its nextnextGaussian
in a staticThreadLocal
instead of in an instance variable asRandom
does.
Overall my cursory inspection seems to reveal an ugly copy of Random
with no advantages over the simple implementation above. But the authors of the standard library are smart so there must be some reason for this weird approach. Does anyone have any insight into why ThreadLocalRandom
was implemented this way?
ThreadLocalRandom
, but I do know that parent types should not know of/depend on their subtypes (in regards to your simpler alternative) – DraffUnsynchronizedRandom
. Either way the major issues with the current implementation are trivially avoided. – CorespondentSplittableRandom
, from which some code is duplicated. – BonnString.substring
changed to copy the substring in Java 7, which affects Java applications. The particular algorithm used for random number generation never should have been documented in such detail and never should have been relied on exactly. I think that's one of the many legacy mistakes in the Java API. – CorespondentString.substring
change was (and still is) a contentious one. I'm not saying the JDK team never makes mistakes, but I'm suggesting starting from an assumption of good intent and competency, rather than using language like "bizarrely", "ugly", "no advantages", and the like. That you don't see the advantages doesn't mean they don't exist. I realize that's what you're trying to get at, but your framing of the question is needlessly presumptuous. I'm simply encouraging giving the JDK folks a little more benefit of the doubt. – Sharpnosed