Skip to content

Instantly share code, notes, and snippets.

@fabiolimace
Last active November 7, 2021 05:20
Show Gist options
  • Save fabiolimace/3841eb2edf69c7347b4cb3f294211dcf to your computer and use it in GitHub Desktop.
Save fabiolimace/3841eb2edf69c7347b4cb3f294211dcf to your computer and use it in GitHub Desktop.
A non-blocking factory that wraps an array of time-based UUID factories
package com.github.f4b6a3.uuid.factory;
import java.security.SecureRandom;
import java.util.UUID;
import java.util.function.Supplier;
import com.github.f4b6a3.uuid.enums.UuidVersion;
import com.github.f4b6a3.uuid.factory.function.impl.DefaultRandomFunction;
import com.github.f4b6a3.uuid.factory.nonstandard.PrefixCombFactory;
import com.github.f4b6a3.uuid.factory.rfc4122.RandomBasedFactory;
import com.github.f4b6a3.uuid.factory.rfc4122.TimeBasedFactory;
import com.github.f4b6a3.uuid.factory.rfc4122.TimeOrderedFactory;
/**
* A class that wraps an array of {@link UuidFactory}.
*
* Each thread is associated with one factory index. The association is not 1 to
* 1, i.e., more than one thread may be associated to the same factory.
*
* The factory index associated with a thread ID is calculated with this
* formula: index = MOD(threadID, arraySize).
*
* This class works like a simple thread local with a fixed pool size and
* without 1 to 1 relationship.
*
* This class can be used to generate more than 10,000,000 UUIDs per second when
* using these factories: {@link TimeBasedFactory}, {@link TimeOrderedFactory}.
* The time-based factories in this library comply the theoretical limit of 10
* million UUIDs per second defined in the RFC-4122.
*
* It is unnecessary to use it with the default {@link RandomBasedFactory}
* (instantiated without arguments), unless you want to pass your own
* {@link Random} or {@link RandomFunction} argument to the constructor.
*/
public final class LessBlockingFactory implements NoArgsFactory {
private final NoArgsFactory[] factories;
/**
* A constructor that instantiates an internal array of factories.
*
* @param size the number of factories to be instantiated.
* @param supplier a supplier that returns a new factory instance.
*/
public LessBlockingFactory(final int size, Supplier<NoArgsFactory> supplier) {
this.factories = new NoArgsFactory[size];
for (int i = 0; i < factories.length; i++) {
factories[i] = supplier.get();
}
}
/**
* Returns a new UUID.
*
* Each thread is associated with one factory index.
*
* The factory index is calculated with this formula: MOD(threadID, arraySize).
*
* @return a UUID
*/
@Override
public UUID create() {
// get the index given the current thread ID
final long tid = Thread.currentThread().getId();
final int index = (int) tid % factories.length;
// use factory associated to the thread
return this.factories[index].create();
}
}
package com.github.f4b6a3.uuid.factory;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.UUID;
import com.github.f4b6a3.uuid.factory.LessBlockingFactory;
import com.github.f4b6a3.uuid.factory.rfc4122.RandomBasedFactory;
import com.github.f4b6a3.uuid.factory.rfc4122.TimeBasedFactory;
public class Test {
public static void main(String[] args) {
// -------------------------------------------------------------------------
// EXAMPLE 1:
// a less-blocking factory that wraps an array of 8 time-based factories
// -------------------------------------------------------------------------
LessBlockingFactory factory1 = new LessBlockingFactory(8, TimeBasedFactory::new);
System.out.println("OUTPUT 1:");
for (int i = 0; i < 10; i++) {
UUID uuid = factory1.create();
System.out.println(uuid);
}
// -------------------------------------------------------------------------
// EXAMPLE 2:
// a less-blocking factory that wraps an array of 8 random-based factories
// -------------------------------------------------------------------------
try {
// Passing as argument a SecureRandom with SHA1PRNG algorithm.
// SHA1PRNG or DRBG can be used to avoid contention from the default SecureRandom.
final SecureRandom argument = SecureRandom.getInstance("SHA1PRNG"); // non-blocking algorithm
LessBlockingFactory factory2 = new LessBlockingFactory(8, () -> new RandomBasedFactory(argument));
System.out.println("OUTPUT 2:");
for (int i = 0; i < 10; i++) {
UUID uuid = factory2.create();
System.out.println(uuid);
}
} catch (NoSuchAlgorithmException e) {
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment