uuidgenerator.java
来自「OpenJMS是一个开源的Java Message Service API 1.」· Java 代码 · 共 899 行 · 第 1/3 页
JAVA
899 行
} if (_uuidsThisTick + 1 < _uuidsPerTick) { // Clock did not advance, but able to create more UUIDs // for this clock, proceed. ++_uuidsThisTick; break; } // Running out of UUIDs for the current clock tick, must // wait until clock advances. Possible that clock did not // advance in background, so try to synchronize it first. clock = Clock.synchronize(); if (clock <= _lastClock) { // if (Configuration.verbose) //Logger.tyrex.debug(Messages.message("tyrex.uuid.fastHolding")); while (clock <= _lastClock) { // UUIDs generated too fast, suspend for a while. try { Thread.currentThread().sleep(Clock.getUnsynchTicks()); } catch (InterruptedException except) { } clock = Clock.synchronize(); } } } // Modify Java clock (milliseconds) to UUID clock (100 nanoseconds). // Add the count of uuids to low order bits of the clock reading, // assuring we get a unique clock. clock = (_lastClock + JAVA_UUID_CLOCK_DIFF) * 100 + _uuidsThisTick; chars = new char[36]; // Add the low field of the clock (4 octets) chars[0] = HEX_DIGITS[(int) ((clock >> 28) & 0x0F)]; chars[1] = HEX_DIGITS[(int) ((clock >> 24) & 0x0F)]; chars[2] = HEX_DIGITS[(int) ((clock >> 20) & 0x0F)]; chars[3] = HEX_DIGITS[(int) ((clock >> 16) & 0x0F)]; chars[4] = HEX_DIGITS[(int) ((clock >> 12) & 0x0F)]; chars[5] = HEX_DIGITS[(int) ((clock >> 8) & 0x0F)]; chars[6] = HEX_DIGITS[(int) ((clock >> 4) & 0x0F)]; chars[7] = HEX_DIGITS[(int) (clock & 0x0F)]; chars[8] = '-'; // Add the medium field of the clock (2 octets) chars[9] = HEX_DIGITS[(int) ((clock >> 44) & 0x0F)]; chars[10] = HEX_DIGITS[(int) ((clock >> 40) & 0x0F)]; chars[11] = HEX_DIGITS[(int) ((clock >> 36) & 0x0F)]; chars[12] = HEX_DIGITS[(int) ((clock >> 32) & 0x0F)]; chars[13] = '-'; // Add the high field of the clock multiplexed with version number (2 octets) chars[14] = HEX_DIGITS[(int) (((clock >> 60) & 0x0F) | UUID_VERSION_CLOCK_OCTET)]; chars[15] = HEX_DIGITS[(int) ((clock >> 56) & 0x0F)]; chars[16] = HEX_DIGITS[(int) ((clock >> 52) & 0x0F)]; chars[17] = HEX_DIGITS[(int) ((clock >> 48) & 0x0F)]; chars[18] = '-'; // Add the clock sequence and version identifier (2 octets) chars[19] = _clockSeqOctet[0]; chars[20] = _clockSeqOctet[1]; chars[21] = _clockSeqOctet[2]; chars[22] = _clockSeqOctet[3]; chars[23] = '-'; // Add the node identifier (6 octets) chars[24] = _nodeIdentifierOctet[0]; chars[25] = _nodeIdentifierOctet[1]; chars[26] = _nodeIdentifierOctet[2]; chars[27] = _nodeIdentifierOctet[3]; chars[28] = _nodeIdentifierOctet[4]; chars[29] = _nodeIdentifierOctet[5]; chars[30] = _nodeIdentifierOctet[6]; chars[31] = _nodeIdentifierOctet[7]; chars[32] = _nodeIdentifierOctet[8]; chars[33] = _nodeIdentifierOctet[9]; chars[34] = _nodeIdentifierOctet[10]; chars[35] = _nodeIdentifierOctet[11]; } return chars; } /** * Returns a time-based UUID as a character array. The UUID * identifier is always 16 bytes long. * * @return A time-based UUID */ public static byte[] createTimeUUIDBytes() { long clock; byte[] bytes; long nextClock; // Acquire lock to assure synchronized generation synchronized (UUIDGenerator.class) { clock = Clock.clock(); while (true) { if (clock > _lastClock) { // Since we are using the clock interval for the UUID // space, we must make sure the next clock provides // sufficient room so UUIDs do not roll over. nextClock = _lastClock + (_uuidsThisTick / 100); if (clock <= nextClock) { clock = Clock.synchronize(); } if (clock > nextClock) { // Clock reading changed since last UUID generated, // reset count of UUIDs generated with this clock. _uuidsThisTick = 0; _lastClock = clock; // Adjust UUIDs per tick in case the clock sleep ticks // have changed. _uuidsPerTick = Clock.getUnsynchTicks() * 100; break; } } if (_uuidsThisTick + 1 < _uuidsPerTick) { // Clock did not advance, but able to create more UUIDs // for this clock, proceed. ++_uuidsThisTick; break; } // Running out of UUIDs for the current clock tick, must // wait until clock advances. Possible that clock did not // advance in background, so try to synchronize it first. clock = Clock.synchronize(); if (clock <= _lastClock) { // if (Configuration.verbose) // Logger.tyrex.debug(Messages.message("tyrex.uuid.fastHolding")); while (clock <= _lastClock) { // UUIDs generated too fast, suspend for a while. try { Thread.currentThread().sleep(Clock.getUnsynchTicks()); } catch (InterruptedException ignore) { } clock = Clock.synchronize(); } } } // Modify Java clock (milliseconds) to UUID clock (100 nanoseconds). // Add the count of uuids to low order bits of the clock reading, // assuring we get a unique clock. clock = (_lastClock + JAVA_UUID_CLOCK_DIFF) * 100 + _uuidsThisTick; bytes = new byte[16]; // Add the low field of the clock (4 octets) bytes[0] = (byte) ((clock >> 24) & 0xFF); bytes[1] = (byte) ((clock >> 16) & 0xFF); bytes[2] = (byte) ((clock >> 8) & 0xFF); bytes[3] = (byte) (clock & 0xFF); // Add the medium field of the clock (2 octets) bytes[4] = (byte) ((clock >> 40) & 0xFF); bytes[5] = (byte) ((clock >> 32) & 0xFF); // Add the high field of the clock multiplexed with version // number (2 octets) bytes[6] = (byte) (((clock >> 60) & 0xFF) | UUID_VERSION_CLOCK_BYTE); bytes[7] = (byte) ((clock >> 48) & 0xFF); // Add the clock sequence and version identifier (2 octets) bytes[8] = _clockSeqByte[0]; bytes[9] = _clockSeqByte[1]; // Add the node identifier (6 octets) bytes[10] = _nodeIdentifierByte[0]; bytes[11] = _nodeIdentifierByte[1]; bytes[12] = _nodeIdentifierByte[2]; bytes[13] = _nodeIdentifierByte[3]; bytes[14] = _nodeIdentifierByte[4]; bytes[15] = _nodeIdentifierByte[5]; } return bytes; } /** * Returns true if the UUID was created on this machine. * Determines the source of the UUID based on the node * identifier. * * @param uuid The UUID as a byte array * @return True if created on this machine */ public static boolean isLocal(byte[] uuid) { if (uuid == null) throw new IllegalArgumentException("Argument uuid is null"); if (uuid.length != 16) return false; return (uuid[10] == _nodeIdentifierByte[0] && uuid[11] == _nodeIdentifierByte[1] && uuid[12] == _nodeIdentifierByte[2] && uuid[13] == _nodeIdentifierByte[3] && uuid[14] == _nodeIdentifierByte[4] && uuid[15] == _nodeIdentifierByte[5]); } /** * Initialise the generator * <p> * This method generates the node identifier and clock sequence, and * sets {@link #_uuidsPerTick} to the number of UUIDs allowed per clock * tick. */ private static void initialize() { // Random random = new SecureRandom(); Random random = new Random(); String nodeIdString; long nodeIdLong; String seqString; int seqInt; // Generate the node identifier, as we can't determine the IEEE 802 // address of the local host. // As a result, it must have bit 48 set. nodeIdLong = random.nextLong(); nodeIdLong = nodeIdLong | (1 << 47); // Generate the clock sequence seqInt = random.nextInt(1 << 12); seqInt = seqInt & 0x1FFF; // Convert clock sequence to 4 hexadecimal digits _clockSeqOctet = new char[4]; _clockSeqOctet[0] = HEX_DIGITS[(int) ((seqInt >> 12) & 0x0F)]; _clockSeqOctet[1] = HEX_DIGITS[(int) ((seqInt >> 8) & 0x0F)]; _clockSeqOctet[2] = HEX_DIGITS[(int) ((seqInt >> 4) & 0x0F)]; _clockSeqOctet[3] = HEX_DIGITS[(int) (seqInt & 0x0F)]; _clockSeqByte = new byte[2]; _clockSeqByte[0] = (byte) ((seqInt >> 8) & 0xFF); _clockSeqByte[1] = (byte) (seqInt & 0xFF); // Need to mask UUID variant on clock sequence _clockSeqOctet[0] = HEX_DIGITS[(int) ((seqInt >> 12) & 0x0F) | UUID_VARIANT_OCTET]; _clockSeqByte[0] = (byte) (((seqInt >> 8) & 0xFF) | UUID_VARIANT_BYTE); // Convert node identifier to 12 hexadecimal digits _nodeIdentifierOctet = new char[12]; for (int i = 0; i < 12; ++i) { _nodeIdentifierOctet[i] = HEX_DIGITS[(int) ((nodeIdLong >> ((11 - i) * 4)) & 0x0F)]; } _nodeIdentifierByte = new byte[6]; for (int i = 0; i < 6; ++i) { _nodeIdentifierByte[i] = (byte) ((nodeIdLong >> ((5 - i) * 8)) & 0xFF); } // The number of UUIDs allowed per tick depends on the number of // ticks between each advance of the clock, adjusted for 100 // nanosecond precision. _uuidsPerTick = Clock.getUnsynchTicks() * 100; } static { initialize(); // This makes sure we miss at least one clock tick, just to be safe. _uuidsThisTick = _uuidsPerTick; _lastClock = Clock.clock(); } public static void main(String[] args) { long clock; HashSet hash; String id; int count = 1000000; for (int i = 0; i < 10; ++i) { System.out.println(create()); } clock = System.currentTimeMillis(); hash = new HashSet(count / 100, 100); for (int i = 0; i < count; ++i) { if ((i % 10000) == 0) System.out.println("Checked " + i); id = create(); if (hash.contains(id)) System.out.println("Duplicate id " + id); else hash.add(id); } clock = System.currentTimeMillis() - clock; System.out.println("Generated " + count + " UUIDs in " + clock + "ms"); } /** * An exception indicating the identifier is invalid and * cannot be converted into an array of bytes. */ public static class InvalidIDException extends Exception { public InvalidIDException(String message) { super(message); } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?