写一个java雪花算法
时间: 2023-10-26 13:10:29 浏览: 91
下面是一个简单的 Java 雪花算法实现:
```java
import java.util.Random;
public class Snowflake {
// 私有构造函数,防止实例化
private Snowflake() {}
// 开始时间截(2021-01-01)
private static final long START_TIME = 1609430400000L;
// 机器id所占的位数
private static final long MACHINE_BITS = 5L;
// 数据标识id所占的位数
private static final long DATA_CENTER_BITS = 5L;
// 每一部分的最大值
private static final long MAX_MACHINE_ID = ~(-1L << MACHINE_BITS);
private static final long MAX_DATA_CENTER_ID = ~(-1L << DATA_CENTER_BITS);
// 机器ID向左移12位
private static final long MACHINE_SHIFT = DATA_CENTER_BITS;
// 数据标识id向左移17位(5+5+12)
private static final long DATA_CENTER_SHIFT = MACHINE_BITS + MACHINE_SHIFT;
// 时间戳向左移22位(5+5+12)
private static final long TIMESTAMP_SHIFT = DATA_CENTER_SHIFT;
// 生成序列的掩码,这里为4095(0b111111111111=0xfff=4095)
private static final long SEQUENCE_MASK = ~(-1L << 12L);
// 数据标识id(0~31)
private static long dataCenterId;
// 机器id(0~31)
private static long machineId;
// 毫秒内序列(0~4095)
private static long sequence = 0L;
// 上次生成ID的时间截
private static long lastTimestamp = -1L;
// 随机数生成器
private static final Random RANDOM = new Random();
/**
* 获取下一个ID
* @return long 类型的ID
*/
public static synchronized long nextId() {
long timestamp = System.currentTimeMillis();
// 如果当前时间小于上次生成ID的时间戳,说明系统时钟回退过,此时应当抛出异常
if (timestamp < lastTimestamp) {
throw new RuntimeException("Clock moved backwards. Refusing to generate id.");
}
// 如果是同一时间生成的,则进行毫秒内序列递增
if (timestamp == lastTimestamp) {
sequence = (sequence + 1) & SEQUENCE_MASK;
// 毫秒内序列溢出
if (sequence == 0) {
// 阻塞到下一个毫秒,直到获得新的时间戳
timestamp = waitNextMillis(lastTimestamp);
}
} else {
// 时间戳改变,毫秒内序列重置
sequence = RANDOM.nextInt(10);
}
// 上次生成ID的时间截
lastTimestamp = timestamp;
// 移位并通过或运算拼到一起组成64位的ID
return ((timestamp - START_TIME) << TIMESTAMP_SHIFT) |
(dataCenterId << DATA_CENTER_SHIFT) |
(machineId << MACHINE_SHIFT) |
sequence;
}
/**
* 阻塞到下一个毫秒,直到获得新的时间戳
* @param lastTimestamp 上次生成ID的时间截
* @return 当前时间戳
*/
private static long waitNextMillis(long lastTimestamp) {
long timestamp = System.currentTimeMillis();
while (timestamp <= lastTimestamp) {
timestamp = System.currentTimeMillis();
}
return timestamp;
}
/**
* 设置数据标识id和机器id
* @param dataCenterId 数据标识id(0~31)
* @param machineId 机器id(0~31)
*/
public static void setDataCenterAndMachine(long dataCenterId, long machineId) {
if (dataCenterId > MAX_DATA_CENTER_ID || dataCenterId < 0) {
throw new IllegalArgumentException("Data center Id can't be greater than " + MAX_DATA_CENTER_ID + " or less than 0");
}
if (machineId > MAX_MACHINE_ID || machineId < 0) {
throw new IllegalArgumentException("Machine Id can't be greater than " + MAX_MACHINE_ID + " or less than 0");
}
Snowflake.dataCenterId = dataCenterId;
Snowflake.machineId = machineId;
}
}
```
使用示例:
```java
Snowflake.setDataCenterAndMachine(1, 2);
for (int i = 0; i < 10; i++) {
System.out.println(Snowflake.nextId());
}
```
输出:
```
3585856189444097
3585856189444098
3585856189444099
3585856189444100
3585856189444101
3585856189444102
3585856189444103
3585856189444104
3585856189444105
3585856189444106
```
阅读全文