Improve ThreadLocal handling in o.e.c.Randomness

This commit improves the handling of ThreadLocal Random instance
allocation in o.e.c.Randomness.
 - the seed per instance is no longer fixed
 - a non-dangerous race to create the ThreadLocal instance has been
   removed
 - encapsulated all state into an static nested class for safe and lazy
   instantiation
This commit is contained in:
Jason Tedor 2015-12-11 19:03:16 -05:00
parent 5f3d807f61
commit a42823ad45
1 changed files with 16 additions and 13 deletions

View File

@ -43,7 +43,6 @@ import java.util.Random;
* DiscoveryService#SETTING_DISCOVERY_SEED)).
*/
public final class Randomness {
private static final SecureRandom SR = new SecureRandom();
private static final Method currentMethod;
private static final Method getRandomMethod;
@ -110,23 +109,27 @@ public final class Randomness {
}
}
private static ThreadLocal<Random> LOCAL;
private static Random getWithoutSeed() {
assert currentMethod == null && getRandomMethod == null : "running under tests but tried to create non-reproducible random";
if (LOCAL == null) {
byte[] bytes = SR.generateSeed(8);
long accumulator = 0;
for (int i = 0; i < bytes.length; i++) {
accumulator = (accumulator << 8) + bytes[i] & 0xFFL;
}
final long seed = accumulator;
LOCAL = ThreadLocal.withInitial(() -> new Random(seed));
}
return LOCAL.get();
return RandomnessHelper.LOCAL.get();
}
public static void shuffle(List<?> list) {
Collections.shuffle(list, get());
}
private static class RandomnessHelper {
private static final SecureRandom SR = new SecureRandom();
private static final ThreadLocal<Random> LOCAL = ThreadLocal.withInitial(
() -> {
byte[] bytes = SR.generateSeed(8);
long accumulator = 0;
for (int i = 0; i < bytes.length; i++) {
accumulator = (accumulator << 8) + bytes[i] & 0xFFL;
}
return new Random(accumulator);
}
);
}
}