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

简介: 雪花算法实现及介绍 (生产可以直接使用)
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();
    }
}


相关文章
|
5月前
|
存储 人工智能 算法
从零掌握贪心算法Java版:LeetCode 10题实战解析(上)
在算法世界里,有一种思想如同生活中的"见好就收"——每次做出当前看来最优的选择,寄希望于通过局部最优达成全局最优。这种思想就是贪心算法,它以其简洁高效的特点,成为解决最优问题的利器。今天我们就来系统学习贪心算法的核心思想,并通过10道LeetCode经典题目实战演练,带你掌握这种"步步为营"的解题思维。
|
6月前
|
机器学习/深度学习 人工智能 搜索推荐
从零构建短视频推荐系统:双塔算法架构解析与代码实现
短视频推荐看似“读心”,实则依赖双塔推荐系统:用户塔与物品塔分别将行为与内容编码为向量,通过相似度匹配实现精准推送。本文解析其架构原理、技术实现与工程挑战,揭秘抖音等平台如何用AI抓住你的注意力。
1597 7
从零构建短视频推荐系统:双塔算法架构解析与代码实现
|
6月前
|
机器学习/深度学习 存储 算法
动态规划算法深度解析:0-1背包问题
0-1背包问题是经典的组合优化问题,目标是在给定物品重量和价值及背包容量限制下,选取物品使得总价值最大化且每个物品仅能被选一次。该问题通常采用动态规划方法解决,通过构建二维状态表dp[i][j]记录前i个物品在容量j时的最大价值,利用状态转移方程避免重复计算子问题,从而高效求解最优解。
732 1
|
6月前
|
算法 搜索推荐 Java
贪心算法:部分背包问题深度解析
该Java代码基于贪心算法求解分数背包问题,通过按单位价值降序排序,优先装入高价值物品,并支持部分装入。核心包括冒泡排序优化、分阶段装入策略及精度控制,体现贪心选择性质,适用于可分割资源的最优化场景。
427 1
贪心算法:部分背包问题深度解析
|
6月前
|
机器学习/深度学习 边缘计算 人工智能
粒子群算法模型深度解析与实战应用
蒋星熠Jaxonic是一位深耕智能优化算法领域多年的技术探索者,专注于粒子群优化(PSO)算法的研究与应用。他深入剖析了PSO的数学模型、核心公式及实现方法,并通过大量实践验证了其在神经网络优化、工程设计等复杂问题上的卓越性能。本文全面展示了PSO的理论基础、改进策略与前沿发展方向,为读者提供了一份详尽的技术指南。
粒子群算法模型深度解析与实战应用
|
6月前
|
机器学习/深度学习 资源调度 算法
遗传算法模型深度解析与实战应用
摘要 遗传算法(GA)作为一种受生物进化启发的优化算法,在复杂问题求解中展现出独特优势。本文系统介绍了GA的核心理论、实现细节和应用经验。算法通过模拟自然选择机制,利用选择、交叉、变异三大操作在解空间中进行全局搜索。与梯度下降等传统方法相比,GA不依赖目标函数的连续性或可微性,特别适合处理离散优化、多目标优化等复杂问题。文中详细阐述了染色体编码、适应度函数设计、遗传操作实现等关键技术,并提供了Python代码实现示例。实践表明,GA的成功应用关键在于平衡探索与开发,通过精心调参维持种群多样性同时确保收敛效率
|
6月前
|
存储 算法 生物认证
基于Zhang-Suen算法的图像细化处理FPGA实现,包含testbench和matlab验证程序
本项目基于Zhang-Suen算法实现图像细化处理,支持FPGA与MATLAB双平台验证。通过对比,FPGA细化效果与MATLAB一致,可有效减少图像数据量,便于后续识别与矢量化处理。算法适用于字符识别、指纹识别等领域,配套完整仿真代码及操作说明。
机器学习/深度学习 算法 自动驾驶
1174 0
|
6月前
|
机器学习/深度学习 人工智能 资源调度
大语言模型的核心算法——简要解析
大语言模型的核心算法基于Transformer架构,以自注意力机制为核心,通过Q、K、V矩阵动态捕捉序列内部关系。多头注意力增强模型表达能力,位置编码(如RoPE)解决顺序信息问题。Flash Attention优化计算效率,GQA平衡性能与资源消耗。训练上,DPO替代RLHF提升效率,MoE架构实现参数扩展,Constitutional AI实现自监督对齐。整体技术推动模型在长序列、低资源下的性能突破。
730 8
|
6月前
|
算法 API 数据安全/隐私保护
深度解析京东图片搜索API:从图像识别到商品匹配的算法实践
京东图片搜索API基于图像识别技术,支持通过上传图片或图片URL搜索相似商品,提供智能匹配、结果筛选、分页查询等功能。适用于比价、竞品分析、推荐系统等场景。支持Python等开发语言,提供详细请求示例与文档。

推荐镜像

更多
  • DNS