雪花id生成工具类SnowflakeIdWorker

`
public class SnowflakeIdWorker {
/**
* 开始时间截 (2015-01-01)
/
private final long twepoch = 1420041600000L;
/
*
* 机器id所占的位数
/
private final long workerIdBits = 5L;
/
*
* 数据标识id所占的位数
/
private final long datacenterIdBits = 5L;
/
*
* 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数)
/
private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
/
*
* 支持的最大数据标识id,结果是31
/
private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
/
*
* 序列在id中占的位数
/
private final long sequenceBits = 12L;
/
*
* 机器ID向左移12位
/
private final long workerIdShift = sequenceBits;
/
*
* 数据标识id向左移17位(12+5)
/
private final long datacenterIdShift = sequenceBits + workerIdBits;
/
*
* 时间截向左移22位(5+5+12)
/
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
/
*
* 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095)
/
private final long sequenceMask = -1L ^ (-1L << sequenceBits);
/
*
* 工作机器ID(0~31)
/
private long workerId;
/
*
* 数据中心ID(0~31)
/
private long datacenterId;
/
*
* 毫秒内序列(0~4095)
/
private long sequence = 0L;
/
*
* 上次生成ID的时间截
*/
private long lastTimestamp = -1L;

/** * 构造函数 * * @param workerId 工作ID (0~31) * @param datacenterId 数据中心ID (0~31) */ public SnowflakeIdWorker(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)); } this.workerId = workerId; this.datacenterId = datacenterId; } /** * 获得下一个ID (该方法是线程安全的) * * @return SnowflakeId */ public 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 long tilNextMillis(long lastTimestamp) { long timestamp = timeGen(); while (timestamp <= lastTimestamp) { timestamp = timeGen(); } return timestamp; } /** * 返回以毫秒为单位的当前时间 * * @return 当前时间(毫秒) */ protected long timeGen() { return System.currentTimeMillis(); }

}`


__EOF__

本文作者Sappy
本文链接https://www.cnblogs.com/Sappy/p/17292870.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Sappy  阅读(63)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示