diff --git a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultRandomFunction.java b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultRandomFunction.java index 09e84a6b..51ea6bea 100644 --- a/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultRandomFunction.java +++ b/src/main/java/com/github/f4b6a3/uuid/factory/function/impl/DefaultRandomFunction.java @@ -26,6 +26,7 @@ import java.security.SecureRandom; import java.util.Random; +import java.util.concurrent.locks.ReentrantLock; import com.github.f4b6a3.uuid.factory.function.RandomFunction; import com.github.f4b6a3.uuid.util.internal.RandomUtil; @@ -35,8 +36,11 @@ *

* The current implementation uses a pool {@link SecureRandom}. *

- * The pool size is equal to the number of processors available, up to a maximum - * of 32. + * The pool size depends on the number of processors available, up to a maximum + * of 32. The minimum is 4. + *

+ * The pool items are deleted very often to avoid holding them for too long. + * They are also deleted to avoid holding more instances than threads running. *

* The PRNG algorithm can be specified by system property or environment * variable. See {@link RandomUtil#newSecureRandom()}. @@ -48,11 +52,20 @@ public final class DefaultRandomFunction implements RandomFunction { private static final int POOL_SIZE = processors(); private static final Random[] POOL = new Random[POOL_SIZE]; + private static final ReentrantLock lock = new ReentrantLock(); @Override public byte[] apply(final int length) { + final byte[] bytes = new byte[length]; current().nextBytes(bytes); + + // every now and then + if (bytes.length > 0 && bytes[0x00] == 0) { + // delete a random item from the pool + delete((new Random()).nextInt(POOL_SIZE)); + } + return bytes; } @@ -61,12 +74,25 @@ private static Random current() { // calculate the pool index given the current thread ID final int index = (int) Thread.currentThread().getId() % POOL_SIZE; - // lazy loading instance - if (POOL[index] == null) { - POOL[index] = RandomUtil.newSecureRandom(); + lock.lock(); + try { + // lazy loading instance + if (POOL[index] == null) { + POOL[index] = RandomUtil.newSecureRandom(); + } + return POOL[index]; + } finally { + lock.unlock(); } + } - return POOL[index]; + private static void delete(int index) { + lock.lock(); + try { + POOL[index] = null; + } finally { + lock.unlock(); + } } private static int processors() {