ID生成(二)SequenceUtil

/**
 * 根据时间戳生产Long型唯一ID 工具类
 *
 * */
public class SequenceUtil {

    /*** 机 器 Id */
    private static long workerId = 0;
    /*** 数 据 中 心 */
    private static long centerId = 0;
    /*** 毫 秒 内 序 列 */
    private static long sequence = 0L;
    /*** 上 次 Id 生 成 的 时 间 戳 */
    private static long lastTimestamp = -1L;
    /** 机 器 编 号 所 占 位 数 */
    private static final long workerIdBits = 5L;
    /** 数 据 标 识 所 占 位 数 */
    private static final long centerIdBits = 5L;
    /** 开 始 时 间 戳 */
    private static final long poc = 1288834974657L;
    /** 序 列 在 Id 中 所 占 的 位 数 */
    private static final long sequenceBits = 12L;
    /** 为 算 法 提 供 可 用 配 置 */
    private static final long workerIdShift = sequenceBits;
    private static final long maxWorkerId = -1L ^ (-1L << workerIdBits);
    private static final long maxCenterId = -1L ^ (-1L << centerIdBits);
    private static final long centerIdShift = sequenceBits + workerIdBits;
    private static final long timestampLeftShift = sequenceBits + workerIdBits + centerIdBits;
    private static final long sequenceMask = -1L ^ (-1L << sequenceBits);
    public static synchronized long makeSequence() throws Exception{
        long timestamp = timeGen();
        // 当 前 时 间 小 于 上 次 Id 生 成 时 间 ,说 明 系 统 时 钟 回 退, 应 会 抛 出 异 常
        if (timestamp < lastTimestamp) {
            // 服 务 器 时 钟 被 调 整 了, Sequence 生 成 器 停 止 服 务
            throw new Exception(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;
        }
        // 暂 存 当 前 时 间 戳 , 为 下 次 使 用  提 供 依 据
        lastTimestamp = timestamp;
        // 雪花算法核心
        return ((timestamp - poc) << timestampLeftShift) | (centerId << centerIdShift) | (workerId << workerIdShift) | sequence;
    }

    /**
     * 获 取 下 一 个 Id
     * */
    public static long makeId(){
        try {
            return makeSequence();
        }catch (Exception e){
            e.printStackTrace();
        }
        return -1;
    }

    /**
     * 获 取 下 一 个 Id ( String 类型 )
     * */
    public static String makeStringId(){
        return String.valueOf(makeId()) ;
    }

    public static List<String> makeStringIds(int size){

        List<String> ids = new ArrayList<String>();
        for (int i = 0;i<size;i++){
            ids.add(makeStringId());
        }
        return ids;
    }

    /**
     * 根 据 一 定 数 量 的 Id
     * */
    public Set<Long> makeId(int initSize) throws Exception{
        Set<Long> ids = new HashSet<Long>(initSize);
        for (long current = 0; current < initSize; current++){
            ids.add(makeId());
        }
        return ids;
    }

    /**
     * 时 间 戳 比 对
     * */
    protected static long tilNextMillis(long lastTimestamp) {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }

    /**
     * 当 前 系 统 时 间 毫 秒
     * */
    protected static long timeGen() {

        return System.currentTimeMillis();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

必成公

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值