雪花算法程序实现及史上最全解析

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 雪花算法实现及介绍 (生产可以直接使用)
importorg.junit.Test;
importorg.junit.runner.RunWith;
importorg.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/*** @author 86182* @date 2023/6/5 15:49* @desc*/publicclassSnowFlakeDemo {
/**起始的时间戳,用于计算时间戳部分*/privatefinalstaticlongSTART_STMP=1480166465631L;
/**序列号占用的位数*/privatefinalstaticlongSEQUENCE_BIT=12;
/**机器标识占用的位数 */privatefinalstaticlongMACHINE_BIT=5;
/**数据中心占用的位数 */privatefinalstaticlongDATA_CENTER_BIT=5;
/**数据中心最大值*//*** 这个运算`-1L ^ (-1L << DATA_CENTER_BIT)`的含义是:* - -1L << DATA_CENTER_BIT是将-1的二进制表示向左移动DATA_CENTER_BIT位,也就是5位。* - 由于-1的二进制表示是除了最高位都是1,向左移动5位后,低5位是1,高位都是0。* - 然后使用`^`运算,即异或运算对-1和向左移动的结果进行运算。* - 由于异或运算遵循交换律和结合律,且异或相同为0,不同为1。* - 所以,最终得到的结果是高5位是1,低位都是0,也就是一个5位的二进制数,其十进制结果就是2^5 - 1 = 31。* 所以,简单来说,该运算的结果是获取一个位数为DATA_CENTER_BIT的二进制数,并将其转换为十进制 - 这里就是31。*/privatefinalstaticlongMAX_DATA_CENTER_NUM=-1L^ (-1L<<DATA_CENTER_BIT);
/**机器标识最大值*/privatefinalstaticlongMAX_MACHINE_NUM=-1L^ (-1L<<MACHINE_BIT);
/**序列号最大值*/privatefinalstaticlongMAX_SEQUENCE=-1L^ (-1L<<SEQUENCE_BIT);
/**机器标识左移位数,12位*/privatefinalstaticlongMACHINE_LEFT=SEQUENCE_BIT;
/**数据中心左移位数,12+5=17位*/privatefinalstaticlongDATA_CENTER_LEFT=SEQUENCE_BIT+MACHINE_BIT;
/**时间戳左移位数,12+5+5=22位*/privatefinalstaticlongTIMESTMP_LEFT=DATA_CENTER_LEFT+DATA_CENTER_BIT;
/**数据中心ID*/privatelongdataCenterId;
/**机器标识ID*/privatelongmachineId;
/**序列号 (备注:对于并发度不高的系统而言,此序列号始终是0,生成的雪花Id末尾一位数字始终为偶数!!!)*/privatelongsequence=0L;
/**上一次时间戳*/privatelonglastStmp=-1L;
publicSnowFlakeDemo(){}
publicSnowFlakeDemo(longdataCenterId, longmachineId) {
/**检验数据中心ID和机器ID合法性,不合法抛出异常*/if (dataCenterId>MAX_DATA_CENTER_NUM||dataCenterId<0) {
thrownewIllegalArgumentException("dataCenterId can't be greater than MAX_DATA_CENTER_NUM or less than 0");
        }
if (machineId>MAX_MACHINE_NUM||machineId<0) {
thrownewIllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0");
        }
/**合法的情况下将参数赋值给类成员变量*/this.dataCenterId=dataCenterId;
this.machineId=machineId;
    }
/**产生下一个ID*/publicsynchronizedlongnextId() {
/**获取当前时间戳,毫秒级*/longcurrStmp=getNewstmp();
/**时间戳回拨,抛出异常*/if (currStmp<lastStmp) {
thrownewRuntimeException("Clock moved backwards.  Refusing to generate id");
        }
/**如果时间戳与上一次相同,序列号自增*/if (currStmp==lastStmp) {
/*** (sequence + 1) & MAX_SEQUENCE 的含义是:* 1. sequence + 1 首先将序列号sequence增加1。* 2. & MAX_SEQUENCE 然后与序列号最大值MAX_SEQUENCE进行与运算。* 3. 由于与运算遵循交换律和结合律,且相同为1,不同为0。* 4. 所以,如果sequence增加后的值没有超过MAX_SEQUENCE,则与运算结果不变,sequence增加后的值仍然保留。* 5. 但如果sequence增加后的值超过了MAX_SEQUENCE,则与运算会将超出的高位全部抹去,只保留低MAX_SEQUENCE位,使得sequence不会超过该最大值。* 所以,该运算的效果是,每次让sequence增加1,但sequence增加后的值不会超过我们设置的MAX_SEQUENCE最大值,一旦超过,高位会被抹去,重新回到低MAX_SEQUENCE位。*/sequence= (sequence+1) &MAX_SEQUENCE;
/**同一毫秒序列号已经最大,等待下一毫秒*/if (sequence==0L) {
currStmp=getNextMill();
            }
        } else {
/**不同毫秒序列号置为0,从0开始*/sequence=0L;
        }
/**更新时间戳为当前时间戳*/lastStmp=currStmp;
/*** 计算ID* 时间戳部分(41 bit)*     数据中心部分(5 bit)*         机器标识部分(5 bit)*             序列号部分(12 bit)*//*** 含义是:* 1. (currStmp - START_STMP) << TIMESTMP_LEFT 首先计算出当前时间戳currStmp减去起始时间戳START_STMP的差值,然后将该差值向左移动TIMESTMP_LEFT位,也就是41位。这步骤生成时间戳部分。* 2. | dataCenterId << DATA_CENTER_LEFT  将数据中心ID向左移动DATA_CENTER_LEFT位,也就是17位,然后使用按位或|运算符将该结果与1步骤的结果进行|运算。这步骤在时间戳部分的基础上添加了数据中心ID部分。* 3. | machineId << MACHINE_LEFT 将机器ID向左移动MACHINE_LEFT位,也就是22位,然后使用按位或运算符将该结果与2步骤的结果进行|运算。这步骤在时间戳部分和数据中心ID部分的基础上添加了机器ID部分。* 4. | sequence 最后,直接使用按位或运算符将序列号sequence与3步骤的结果进行|运算,添加序列号部分,得到最终完整的ID。* 5. 通过这4步运算,我们按照时间戳→数据中心ID→机器ID→序列号的顺序,一步步构建完整的ID。这与雪花ID的结构与顺序是一致的。* 所以,这句运算的含义就是按照部分→部分的方式构建完整的雪花ID,每一步都使用按位或运算,这是一种高效的ID构建方式。这是雪花算法实现的关键所在。*/return (currStmp-START_STMP) <<TIMESTMP_LEFT|dataCenterId<<DATA_CENTER_LEFT|machineId<<MACHINE_LEFT|sequence;
    }
/*** 等待下一毫秒** @return*/privatelonggetNextMill() {
longmill=getNewstmp();
while (mill<=lastStmp) {
mill=getNewstmp();
        }
returnmill;
    }
/*** 获取当前时间戳,毫秒级* @return*/privatelonggetNewstmp() {
returnSystem.currentTimeMillis();
    }
}


相关文章
|
10天前
|
算法 前端开发 数据处理
小白学python-深入解析一位字符判定算法
小白学python-深入解析一位字符判定算法
26 0
|
3天前
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
16 3
|
5天前
|
搜索推荐 算法
插入排序算法的平均时间复杂度解析
【10月更文挑战第12天】 插入排序是一种简单直观的排序算法,通过不断将未排序元素插入到已排序部分的合适位置来完成排序。其平均时间复杂度为$O(n^2)$,适用于小规模或部分有序的数据。尽管效率不高,但在特定场景下仍具优势。
|
4天前
|
存储 缓存 算法
如何通过优化算法和代码结构来提升易语言程序的执行效率?
如何通过优化算法和代码结构来提升易语言程序的执行效率?
|
4天前
|
监控 算法 数据安全/隐私保护
基于三帧差算法的运动目标检测系统FPGA实现,包含testbench和MATLAB辅助验证程序
本项目展示了基于FPGA与MATLAB实现的三帧差算法运动目标检测。使用Vivado 2019.2和MATLAB 2022a开发环境,通过对比连续三帧图像的像素值变化,有效识别运动区域。项目包括完整无水印的运行效果预览、详细中文注释的代码及操作步骤视频,适合学习和研究。
|
11天前
|
机器学习/深度学习 算法 PyTorch
Pytorch-RMSprop算法解析
关注B站【肆十二】,观看更多实战教学视频。本期介绍深度学习中的RMSprop优化算法,通过调整每个参数的学习率来优化模型训练。示例代码使用PyTorch实现,详细解析了RMSprop的参数及其作用。适合初学者了解和实践。
19 1
|
5天前
|
前端开发 算法 JavaScript
无界SaaS模式深度解析:算力算法、链接力、数据确权制度
私域电商的无界SaaS模式涉及后端开发、前端开发、数据库设计、API接口、区块链技术、支付和身份验证系统等多个技术领域。本文通过简化框架和示例代码,指导如何将核心功能转化为技术实现,涵盖用户管理、企业店铺管理、数据流量管理等关键环节。
|
10天前
|
XML Java 数据格式
手动开发-简单的Spring基于注解配置的程序--源码解析
手动开发-简单的Spring基于注解配置的程序--源码解析
24 0
|
10天前
|
XML Java 数据格式
手动开发-简单的Spring基于XML配置的程序--源码解析
手动开发-简单的Spring基于XML配置的程序--源码解析
38 0
|
11天前
|
机器学习/深度学习 算法 PyTorch
Pytorch-SGD算法解析
SGD(随机梯度下降)是机器学习中常用的优化算法,特别适用于大数据集和在线学习。与批量梯度下降不同,SGD每次仅使用一个样本来更新模型参数,提高了训练效率。本文介绍了SGD的基本步骤、Python实现及PyTorch中的应用示例。
24 0

热门文章

最新文章

推荐镜像

更多