1 package com.xiaozhou.springbootwiki.util; 2 3 //@Component 4 public class SnowflakeIdWorker { 5 // 起始的时间戳(自定义,例如系统上线时间) 6 private final long twepoch = 1732162441000L; 7 8 // 机器id所占的位数 9 private final long workerIdBits = 5L; 10 11 // 数据标识id所占的位数 12 private final long datacenterIdBits = 5L; 13 14 // 最大机器ID 15 private final long maxWorkerId = -1L ^ (-1L << workerIdBits); 16 17 // 最大数据标识ID 18 private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); 19 20 // 序列在id中占的位数 21 private final long sequenceBits = 12L; 22 23 // 机器ID左移12位 24 private final long workerIdShift = sequenceBits; 25 26 // 数据标识id左移17位(12+5) 27 private final long datacenterIdShift = sequenceBits + workerIdBits; 28 29 // 时间截左移22位(5+5+12) 30 private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; 31 32 // 序列的掩码,这里为4095 (0b111111111111=4095) 33 private final long sequenceMask = -1L ^ (-1L << sequenceBits); 34 35 // 上次生成ID的时间截 36 private long lastTimestamp = -1L; 37 38 // 序列号 39 private long sequence = 0L; 40 41 // 工作机器ID 42 private final long workerId; 43 44 // 数据中心ID 45 private final long datacenterId; 46 47 public SnowflakeIdWorker(long workerId, long datacenterId) { 48 if (workerId > maxWorkerId || workerId < 0) { 49 throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); 50 } 51 if (datacenterId > maxDatacenterId || datacenterId < 0) { 52 throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); 53 } 54 this.workerId = workerId; 55 this.datacenterId = datacenterId; 56 } 57 58 // 生成ID 59 public synchronized long nextId() { 60 long timestamp = timeGen(); 61 62 // 如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退,抛出异常 63 if (timestamp < lastTimestamp) { 64 throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); 65 } 66 67 // 如果时间戳相同,则序列号自增 68 if (lastTimestamp == timestamp) { 69 sequence = (sequence + 1) & sequenceMask; 70 // 序列号溢出,等待下一毫秒 71 if (sequence == 0) { 72 timestamp = tilNextMillis(lastTimestamp); 73 } 74 } else { 75 // 时间戳改变,序列号重置为0 76 sequence = 0L; 77 } 78 79 // 更新最后的时间戳 80 lastTimestamp = timestamp; 81 82 // 移位并通过或运算拼到一起组成64位的ID 83 return ((timestamp - twepoch) << timestampLeftShift) | 84 (datacenterId << datacenterIdShift) | 85 (workerId << workerIdShift) | 86 sequence; 87 } 88 89 // 获取当前时间戳 90 protected long timeGen() { 91 return System.currentTimeMillis(); 92 } 93 94 // 等待下一个毫秒 95 protected long tilNextMillis(long lastTimestamp) { 96 long timestamp = timeGen(); 97 while (timestamp <= lastTimestamp) { 98 timestamp = timeGen(); 99 } 100 return timestamp; 101 } 102 103 public static void main(String[] args) { 104 SnowflakeIdWorker idWorker = new SnowflakeIdWorker(1, 1); 105 long start = System.currentTimeMillis(); 106 for (int i = 0; i < 100000L; i++) { 107 System.out.println(idWorker.nextId()); 108 } 109 System.out.println(System.currentTimeMillis() - start); 110 } 111 }
标签:sequence,timestamp,lastTimestamp,private,datacenterId,111,long From: https://www.cnblogs.com/sys520/p/18560450