一、UUID簡介
UUID(Universally Unique Identifier)是一種標識符,由一組32個十六進制數所構成,其理論上的唯一性是通過時間戳和隨機數來保證的。
Java中的UUID是通過java.util.UUID類來實現的,其主要有以下幾種方法:
/** * 靜態方法,返回一個隨機生成的UUID。 * @return 隨機生成的UUID */ public static UUID randomUUID() {...} /** * 靜態方法,返回一個根據指定字節數組生成的UUID。 * @param input 字節數組 * @return 根據指定字節數組生成的UUID */ public static UUID nameUUIDFromBytes(byte[] input) {...} /** * 構造方法,根據指定的參數生成UUID * @param mostSigBits 64位的最高有效位 * @param leastSigBits 64位的最低有效位 */ private UUID(long mostSigBits, long leastSigBits) {...}
二、UUID的唯一性
UUID的唯一性是通過時間戳和隨機數來保證的,其中時間戳的精度是100納秒,而隨機數則是通過SecureRandom類的實例生成的。因此,UUID的重複概率相當地小。
一方面從理論上講,如果一個系統每微秒生成一條UUID,那麼大約需要3.4×10^38年才能出現重複的UUID。另一方面,UUID的長度為128位,實際上是超過目前世界人口數量的。
因此,可以認為Java UUID幾乎是唯一的。不過,在實際應用中,我們仍然需要考慮UUID重複的情況。
三、UUID重複的情況
1.多線程環境下UUID重複
在多線程環境下,如果多個線程同時調用Java UUID的randomUUID()方法,那麼可能會出現UUID重複的情況。
為了避免這種情況,我們可以使用ThreadLocalRandom類代替SecureRandom類,即:
UUID uuid = new UUID(ThreadLocalRandom.current().nextLong(), ThreadLocalRandom.current().nextLong());
2.分布式環境下UUID重複
在分布式環境下,如果多個節點同時生成UUID,那麼也會出現UUID重複的情況。
為了解決這個問題,我們可以使用第三方的UUID生成器,比如UUIDGenerator、Snowflake等。
下面是使用Snowflake算法生成UUID的Java示例:
public class IdWorker { private long workerId; private long datacenterId; private long sequence = 0L; private long twepoch = 1288834974657L; private long workerIdBits = 5L; private long datacenterIdBits = 5L; private long maxWorkerId = -1L ^ (-1L << workerIdBits); private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); private long sequenceBits = 12L; private long workerIdShift = sequenceBits; private long datacenterIdShift = sequenceBits + workerIdBits; private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; private long sequenceMask = -1L ^ (-1L < maxWorkerId || workerId maxDatacenterId || datacenterId < 0) { throw new IllegalArgumentException("datacenterId cannot be greater than " + maxDatacenterId + " or less than 0"); } this.workerId = workerId; this.datacenterId = datacenterId; } public synchronized long nextId() { long timestamp = timeGen(); if (timestamp < lastTimestamp) { throw new RuntimeException("Clock moved backwards. Refusing to generate id"); } if (lastTimestamp == timestamp) { sequence = (sequence + 1) & sequenceMask; if (sequence == 0) { timestamp = tilNextMillis(lastTimestamp); } } else { sequence = 0L; } lastTimestamp = timestamp; return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence; } private long tilNextMillis(long lastTimestamp) { long timestamp = timeGen(); while (timestamp <= lastTimestamp) { timestamp = timeGen(); } return timestamp; } private long timeGen() { return System.currentTimeMillis(); } public static void main(String[] args) { IdWorker idWorker = new IdWorker(0, 0); for (int i = 0; i < 100; i++) { System.out.println(idWorker.nextId()); } } }
四、結論
總的來說,Java UUID的理論唯一性是較高的,但在實際應用中仍需要考慮UUID重複的情況。針對不同的情況,我們可以採用不同的解決方案,比如使用ThreadLocalRandom類、第三方UUID生成器、自定義算法等。在使用的時候,一定要根據實際情況進行選擇並進行合理的使用和調整,以保證系統的性能和穩定性。
原創文章,作者:YCLV,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/134710.html