Java 实现的SnowFlake生成UUID (Java代码实战-007)详解编程语言

 SnowFlake所生成的ID一共分成四部分:

1.第一位
占用1bit,其值始终是0,没有实际作用。

2.时间戳
占用41bit,精确到毫秒,总共可以容纳约69 年的时间。

3.工作机器id
占用10bit,其中高位5bit是数据中心ID(datacenterId),低位5bit是工作节点ID(workerId),做多可以容纳1024个节点。

4.序列号
占用12bit,这个值在同一毫秒同一节点上从0开始不断累加,最多可以累加到4095。

SnowFlake算法在同一毫秒内最多可以生成多少个全局唯一ID呢?只需要做一个简单的乘法:

同一毫秒的ID数量 = 1024 X 4096 = 4194304

这个数字在绝大多数并发场景下都是够用的。

import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
/** 
* Created by xfyou 2018/6/8 14:01. 
*/ 
public class SnowFlakeIdGenerator { 
// The initial time(2017-01-01) 
private static final long INITIAL_TIME_STAMP = 1483200000000L; 
// Machine ID bits 
private static final long WORK_ID_BITS = 5L; 
// DataCenter ID bits 
private static final long DATACENTER_ID_BITS = 5L; 
// The maximum machine ID supported is 31, which can quickly calculate the maximum decimal number that a few binary numbers can represent. 
private static final long MAX_WORKER_ID = ~(-1L << WORK_ID_BITS); 
// The maximum datacenter ID supported is 31 
private static final long MAX_DATACENTER_ID = ~(-1L << DATACENTER_ID_BITS); 
// Sequence ID bits 
private static final long SEQUENCE_BITS = 12L; 
// The machine ID offset,12 
private static final long WORKERID_OFFSET = SEQUENCE_BITS; 
// The datacent ID offset,12+5 
private static final long DATACENTERID_OFFSET = WORK_ID_BITS + SEQUENCE_BITS; 
// The timestape offset, 5+5+12 
private static final long TIMESTAMP_OFFSET = DATACENTER_ID_BITS + WORK_ID_BITS + SEQUENCE_BITS; 
// Sequence mask,4095 
private static final long SEQUENCE_MASK = ~(-1L << SEQUENCE_BITS); 
// Worker ID ,0~31 
private long workerId; 
// Datacenter ID,0~31 
private long datacenterId; 
// Sequence,0~4095 
private long sequence = 0L; 
// Last timestamp 
private long lastTimestamp = -1L; 
public SnowFlakeIdGenerator(long workerId, long datacenterId) { 
if (workerId > MAX_WORKER_ID || workerId < 0) 
throw new IllegalArgumentException(String.format("WorkerID can't be greater than %d or less than 0", MAX_WORKER_ID)); 
if (datacenterId > MAX_DATACENTER_ID || datacenterId < 0) 
throw new IllegalArgumentException(String.format("DataCenterID can't be greater than %d or less than 0", MAX_WORKER_ID)); 
this.workerId = workerId; 
this.datacenterId = datacenterId; 
} 
public synchronized long nextId() { 
long timeStamp = System.currentTimeMillis(); 
if (timeStamp < lastTimestamp) 
throw new RuntimeException("The current time less than last time"); 
if (timeStamp == lastTimestamp) { 
sequence = (sequence + 1) & SEQUENCE_MASK; 
if (0 == sequence) 
timeStamp = tillNextMillis(lastTimestamp); 
} else { 
sequence = 0L; 
} 
lastTimestamp = timeStamp; 
return (timeStamp - INITIAL_TIME_STAMP) << TIMESTAMP_OFFSET | (datacenterId << DATACENTERID_OFFSET) | (workerId << WORKERID_OFFSET) | sequence; 
} 
private long tillNextMillis(long lastTimestamp) { 
long timestamp = System.currentTimeMillis(); 
while (timestamp <= lastTimestamp) 
timestamp = System.currentTimeMillis(); 
return timestamp; 
} 
public static void main(String[] args) { 
SnowFlakeIdGenerator generator = new SnowFlakeIdGenerator(1, 1); 
ExecutorService executorService = Executors.newCachedThreadPool(); 
for (int i = 0; i < 5; i++) { 
executorService.execute(new Runnable() { 
@Override 
public void run() { 
long id = generator.nextId(); 
System.out.println(id); 
} 
}); 
} 
executorService.shutdown(); 
} 
}

 一个可能的输出为:

189783462515970048 
189783462515970049 
189783462515970050 
189783462515970051 
189783462520164352

 

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/15925.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论