教我写一个雪花算法工具类,要求新手能看懂,注释要详细
时间: 2023-05-25 17:06:02 浏览: 80
以下是一个简单的雪花算法工具类,它可以生成具有唯一标识符的ID。
```java
public class SnowflakeUtil {
// 每一部分占用的位数,共64位
private static final long SEQUENCE_BITS = 12; // 序列号占用的位数
private static final long MACHINE_ID_BITS = 5; // 机器标识占用的位数
private static final long DATA_CENTER_ID_BITS = 5;// 数据中心占用的位数
// 每一部分的最大值
private static final long MAX_SEQUENCE_NUM = ~(-1L << SEQUENCE_BITS);
private static final long MAX_MACHINE_ID = ~(-1L << MACHINE_ID_BITS);
private static final long MAX_DATA_CENTER_ID = ~(-1L << DATA_CENTER_ID_BITS);
// 每一部分向左的位移
private static final long MACHINE_LEFT_SHIFT = SEQUENCE_BITS;
private static final long DATA_CENTER_LEFT_SHIFT = SEQUENCE_BITS + MACHINE_ID_BITS;
private static final long TIMESTAMP_LEFT_SHIFT = DATA_CENTER_LEFT_SHIFT + DATA_CENTER_ID_BITS;
// 开始时间戳,可以设置一个固定的值,避免占用太多位
private final long START_TIMESTAMP = 1480166465631L; //2016-11-26 21:21:05.631
// 变量部分,可通过构造函数进行初始化
private long dataCenterId; // 数据中心ID
private long machineId; // 机器标识ID
private volatile long sequenceNum = 0L; // 序列号
private long lastTimestamp = -1L; // 最近一次生成ID的时间戳
/**
* 构造函数
*
* @param dataCenterId 数据中心ID,最大值为31
* @param machineId 机器标识ID,最大值为31
*/
public SnowflakeUtil(long dataCenterId, long machineId) throws IllegalArgumentException {
if (dataCenterId > MAX_DATA_CENTER_ID || dataCenterId < 0) {
throw new IllegalArgumentException("DataCenterId can't be greater than " + MAX_DATA_CENTER_ID + " or less than 0");
}
if (machineId > MAX_MACHINE_ID || machineId < 0) {
throw new IllegalArgumentException("MachineId can' be greater than " + MAX_MACHINE_ID + " or less than 0");
}
this.dataCenterId = dataCenterId;
this.machineId = machineId;
}
/**
* 生成ID
*
* @return 返回生成的ID
*/
public synchronized long nextId() {
long currentTimestamp = System.currentTimeMillis();
if (currentTimestamp < lastTimestamp) {
throw new RuntimeException("Clock moved backwards. Refusing to generate id");
}
if (currentTimestamp == lastTimestamp) {
sequenceNum = (sequenceNum + 1) & MAX_SEQUENCE_NUM;
if (sequenceNum == 0L) {
currentTimestamp = tillNextMillis(lastTimestamp);
}
} else {
sequenceNum = 0L;
}
lastTimestamp = currentTimestamp;
return ((currentTimestamp - START_TIMESTAMP) << TIMESTAMP_LEFT_SHIFT) | (dataCenterId << DATA_CENTER_LEFT_SHIFT) | (machineId << MACHINE_LEFT_SHIFT) | sequenceNum;
}
/**
* 如果当前时间与lastTimestamp相等,则等待到下一毫秒
*
* @param lastTimestamp 上次生成ID的时间戳
* @return 当前时间戳
*/
private long tillNextMillis(long lastTimestamp) {
long currentTimestamp = System.currentTimeMillis();
while (currentTimestamp <= lastTimestamp) {
currentTimestamp = System.currentTimeMillis();
}
return currentTimestamp;
}
}
```
此雪花算法工具类主要涉及到的知识点有:
- 序列号、机器标识、数据中心编号按照一定的位数分配,位数越高,则生成的ID越大,ID生成能力也就越强;
- 位移运算是用于将各部分的位数分配,用于ID的生成;
- 通过对每部分的位数进行限制,可以保证ID生成的唯一性;
- 在多线程的环境下,通过加锁的方式实现对序列号计数的同步。
注意事项:
- 由于时间戳和序列号都是在机器的内存中进行计数,它们不是严格的递增,可能会存在重复的情况;
- 如果能够保证分配给的机器标识和数据中心状态的唯一性,则可以在分配时将其中的位先预留一部分空间,将在时间戳和序列号中留下来的位数相应减少,从而增加ID生成的能力。
关于雪花算法的详细解释可以参考这篇文章:[雪花算法(SnowFlake)详解](https://juejin.cn/post/6844903684278222344)。
相关推荐
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)