📄 uuidgenerator.java
字号:
}
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();
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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -