首页 > 编程知识 正文

雪花算法突破69年限制(java常用utils工具类)

时间:2023-05-06 17:17:44 阅读:73788 作者:4144

创建SnowFlake的工具类并粘贴以下代码即可

/* * Twitter _ snow flake br * snow flake的结构如下(各部分用-分开) 3360br* 0-00000000-000000000000-00000000 ) 0000000-000000000000000000000000000000000000000000000000000000000000000000000000000000:1:1:1:0000000000000000000000000000000000 注意,41位时间戳不是存储当前时间的时间戳,而是存储时间戳的差值(当前时间戳-起始时间戳) )的值)一般来说,我们的id生成器开始使用的时间是我们的程序(以下程序IdWorker类的startTime属性) : * 41位时间戳可用69年,年份t=(1L41 )/(1000L * 60 * 60 * 24 * 365 )=69br * 10位数据机的位为, 12位计数序列号可位于包含5位数据中心和5位工作器的1024个节点上,支持每个节点每毫秒(同一台计算机,同一时间戳)生成4096个ID号br * br * SnowFlake的优点是总体上根据时间的推移进行排序,在整个分布式系统中不会发生ID冲突(由数据中心ID和计算机ID区分),而且效率很高。 * SnowFlake每秒发生26万ID左右。 */=========================fields================/**数据标识符所占位数*/privatestaticfinallongdatacenteridbits=5l; /**支持的最大机器id为31 (该移位算法能够立即计算出最多可由几位二进制表示的十进制数(*/privatestaticfinallongmaxworkerid=-1l ^ (-1 ) /**支持的最大数据徽标id为31 */privatestaticfinallongmaxdatacenterid=-1l ^ (-1 ldatacenteridbits ); /**序列在id中所占的位数*/privatestaticfinallongsequencebits=12l; /**将计算机ID向左移动12位* /专用longworkeridshift=sequence bits; /**数据id向左17位(12 )5) /专用longdatacenteridshift=sequencebitsworkeridbits; /**将时间向左偏移22位(5) 12 ) /专用longtimestampleftshift=sequencebitsworkeridbitsdatacenteridbits; /**生成序列的掩码,在此为4095(0b111111111111=0xfff=4095 ) /专用性staticfinallongsequencemask=-1l ^ (-1 lsequencebits ); /**工作装置id(0~31 ) ) * /专用静态长工作器id; /**数据中心id (0到31 (* /私有状态克隆数据中心id; /**毫秒内的序列(0至0~4095 ) * /私有静态长序列=0l; /**上次ID生成的时间戳*/privatestaticlonglasttimestamp=-1l; //======================constructors==================

kerId * 工作ID (0~31) * @param datacenterId * 数据中心ID (0~31) */ public SnowFlake(long workerId, long datacenterId) { if (workerId > maxWorkerId || workerId < 0) { throw new IllegalArgumentException(String.format( "worker Id can't be greater than %d or less than 0", maxWorkerId)); } if (datacenterId > maxDatacenterId || datacenterId < 0) { throw new IllegalArgumentException(String.format( "datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); } SnowFlake.workerId = workerId; SnowFlake.datacenterId = datacenterId; } // ==============================Methods========================================== /** * 获得下一个ID (该方法是线程安全的) * * @return SnowflakeId */ public static synchronized long nextId() { long timestamp = timeGen(); // 如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常 if (timestamp < lastTimestamp) { throw new RuntimeException( String.format( "Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); } // 如果是同一时间生成的,则进行毫秒内序列 if (lastTimestamp == timestamp) { sequence = (sequence + 1) & sequenceMask; // 毫秒内序列溢出 if (sequence == 0) { // 阻塞到下一个毫秒,获得新的时间戳 timestamp = tilNextMillis(lastTimestamp); } } // 时间戳改变,毫秒内序列重置 else { sequence = 0L; } // 上次生成ID的时间截 lastTimestamp = timestamp; // 移位并通过或运算拼到一起组成64位的ID return ((timestamp - twepoch) << timestampLeftShift) // | (datacenterId << datacenterIdShift) // | (workerId << workerIdShift) // | sequence; } /** * 阻塞到下一个毫秒,直到获得新的时间戳 * * @param lastTimestamp * 上次生成ID的时间截 * @return 当前时间戳 */ protected static long tilNextMillis(long lastTimestamp) { long timestamp = timeGen(); while (timestamp <= lastTimestamp) { timestamp = timeGen(); } return timestamp; } /** * 返回以毫秒为单位的当前时间 * * @return 当前时间(毫秒) */ protected static long timeGen() { return System.currentTimeMillis(); } public SnowFlake() { this(0, 0); } // 生成id public static String getId() { return String.valueOf(SnowFlake.nextId()); } // ==============================Test============================================= /** 测试 */ public static void main(String[] args) { System.out.println(SnowFlake.nextId()); }

注:本文为转载文章,因为转载的人太多了,并且都没有标注出原作者,所以原创作者无从考究。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。