教我写一个雪花算法工具类,要求新手能看懂,注释要详细,语言是java
时间: 2023-05-25 18:06:03 浏览: 128
好的,以下是一个简单的Java版雪花算法工具类:
```
/**
* 雪花算法工具类
*/
public class SnowflakeIdWorker {
// 初始时间戳,建议设置为项目启动时间
private final static long START_STAMP = 1567354783982L;
// 序列号占用的位数
private final static long SEQUENCE_BIT = 12;
// 机器标识占用的位数
private final static long MACHINE_BIT = 5;
// 数据中心占用的位数
private final static long DATA_CENTER_BIT = 5;
// 最大序列号
private final static long MAX_SEQUENCE = ~(-1L << SEQUENCE_BIT);
// 最大机器标识
private final static long MAX_MACHINE_ID = ~(-1L << MACHINE_BIT);
// 最大数据中心标识
private final static long MAX_DATA_CENTER_ID = ~(-1L << DATA_CENTER_BIT);
// 机器标识向左移动的位数
private final static long MACHINE_LEFT = SEQUENCE_BIT;
// 数据中心标识向左移动的位数
private final static long DATA_CENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
// 时间戳向左移动的位数
private final static long TIMESTAMP_LEFT = DATA_CENTER_LEFT + DATA_CENTER_BIT;
// 数据中心标识
private long dataCenterId;
// 机器标识
private long machineId;
// 序列号
private long sequence = 0L;
// 上次生成ID的时间戳
private long lastStamp = -1L;
/**
* 构造函数
*
* @param dataCenterId 数据中心标识
* @param machineId 机器标识
*/
public SnowflakeIdWorker(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");
}
this.dataCenterId = dataCenterId;
this.machineId = machineId;
}
/**
* 生成下一个ID
*
* @return ID
*/
public synchronized long nextId() {
long currentStamp = getNewStamp();
if (currentStamp < lastStamp) {
throw new RuntimeException("Clock moved backwards. Refusing to generate id");
}
if (currentStamp == lastStamp) {
sequence = (sequence + 1) & MAX_SEQUENCE;
if (sequence == 0) {
currentStamp = getNextMillis();
}
} else {
sequence = 0L;
}
lastStamp = currentStamp;
return (currentStamp - START_STAMP) << TIMESTAMP_LEFT | dataCenterId << DATA_CENTER_LEFT | machineId << MACHINE_LEFT | sequence;
}
/**
* 获取下一个时间戳
*
* @return 时间戳
*/
private long getNextMillis() {
long currentStamp = getNewStamp();
while (currentStamp <= lastStamp) {
currentStamp = getNewStamp();
}
return currentStamp;
}
/**
* 获取当前时间戳
*
* @return 时间戳
*/
private long getNewStamp() {
return System.currentTimeMillis();
}
public static void main(String[] args) {
SnowflakeIdWorker snowflake = new SnowflakeIdWorker(1, 1);
for (int i = 0; i < 10; i++) {
System.out.println(snowflake.nextId());
}
}
}
```
该工具类实现了雪花算法,可以生成全局唯一的ID。以下是该工具类的主要特点:
- 可以设置数据中心标识和机器标识,以保证不同数据中心或不同机器生成不同的ID。
- 支持多线程环境下生成唯一ID。
- 生成的ID包含时间戳,可以根据ID快速定位到生成时间。
需要注意的是,该工具类生成的ID并不是完美的,因为有可能会出现时钟回拨的情况。在时钟回拨的情况下,更早的时间戳可能会比更晚的时间戳先生成ID。因此,建议在使用雪花算法生成ID时,将系统时间同步到网络时间服务或使用其他可靠的时间获取方式来避免时钟回拨的问题。
阅读全文