Last active
November 7, 2021 05:20
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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(); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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