• IdGenerator(雪花)


    /**
    * tweeter的snowflake 移植到Java.参考资料:https://github.com/twitter/snowflake
    * id构成: 42位的时间前缀 + 10位的节点标识 + 12位的sequence避免并发的数字(12位不够用时强制得到新的时间前缀)
    * id单调递增,长整型
    * 注意这里进行了小改动: snowkflake是5位的datacenter加5位的机器id; 这里变成使用10位的机器id
    * snowkflake当时间调整时将拒绝分配ID,这里改成分配UUID的tMostSignificantBits
    * 通过取服务器名中的编号来分配机器id,实现了去中心化【仅适用于包含编号的机器】
    * 使用:long id = IdGenerator.nextId();
    */
    @Log4j2
    public final class IdGenerator {
    /**
    * 每台机器分配不同的id
    */
    private static final long WORKER_ID;

    /**
    * 时间起始标记点,作为基准,一般取系统的最近时间
    */
    private static final long EPOCH_NUM = 1568017964000L;

    /**
    * 机器标识位数
    */
    private static final long WORKER_IDBITS = 10L;

    /**
    * 机器ID最大值: 1023
    */
    private static final long MAXWORKER_ID = -1L ^ -1L << WORKER_IDBITS;

    /**
    * 毫秒内自增位
    */
    private static final long SEQUENCE_BITS = 12L;

    /**
    * 12
    */
    private static final long WORKER_IDSHIFT = SEQUENCE_BITS;

    /**
    * 22
    */
    private static final long TIMESTAMP_LEFTSHIFT = WORKER_IDBITS + SEQUENCE_BITS;

    /**
    * 4095,111111111111,12位
    */
    private static final long SEQUENCE_MASK = -1L ^ -1L << SEQUENCE_BITS;

    /**
    * 0,并发控制
    */
    private static long sequenceSe = 0L;

    private static long lastTimestamp = -1L;

    static {
    String hostName = null;
    try {
    InetAddress netAddress = InetAddress.getLocalHost();
    hostName = netAddress.getHostName();
    } catch (UnknownHostException e) {
    log.error(e);
    }
    if (null != hostName && !"".equals(hostName)) {
    String hostNo = "";
    for (int i = 0; i < hostName.length(); i++) {
    if (hostName.charAt(i) > 48 && hostName.charAt(i) <= 57) {
    // 取最后一组数字
    if ("".equals(hostNo)) {
    hostNo += hostName.charAt(i);
    } else {
    hostNo = "";
    hostNo += hostName.charAt(i);
    }
    }
    }
    if (!"".equals(hostNo)) {
    WORKER_ID = Integer.parseInt(hostNo) % MAXWORKER_ID;
    } else {
    WORKER_ID = new SecureRandom().nextInt(1000) + 1;
    }

    } else {
    WORKER_ID = new SecureRandom().nextInt(1000) + 1;
    }
    }

    /**
    * Next id long.
    *
    * @return the long
    */
    public static synchronized long nextId() {
    long timestamp = timeGen();
    // 如果上一个timestamp与新产生的相等,则sequence加一(0-4095循环); 对新的timestamp,sequence从0开始
    if (lastTimestamp == timestamp) {
    sequenceSe = sequenceSe + 1 & SEQUENCE_MASK;
    if (sequenceSe == 0) {
    // 重新生成timestamp
    timestamp = tilNextMillis(lastTimestamp);
    }
    } else {
    sequenceSe = 0;
    }

    if (timestamp < lastTimestamp) {
    UUID uuid = UUID.randomUUID();
    return uuid.getMostSignificantBits();
    }

    lastTimestamp = timestamp;
    return timestamp - EPOCH_NUM << TIMESTAMP_LEFTSHIFT | WORKER_ID << WORKER_IDSHIFT | sequenceSe;
    }

    /**
    *
    */
    /**
    * 等待下一个毫秒的到来, 保证返回的毫秒数在参数lastTimestamp之后
    *
    * @param lastTimestamp the last Timestamp
    * @return the long
    */
    private static long tilNextMillis(long lastTimestamp) {
    long timestamp = timeGen();
    while (timestamp <= lastTimestamp) {
    timestamp = timeGen();
    }
    return timestamp;
    }

    /**
    * 获得系统当前毫秒数
    *
    * @return the long
    */
    public static long timeGen() {
    return System.currentTimeMillis();
    }

    }
  • 相关阅读:
    JAVA-初步认识-第十一章-异常-原理异常对象的抛出throw
    shopex后台上传模板漏洞
    PHP使用1个crontab管理多个crontab任务
    HTML5跨浏览器表单及HTML5表单的渐进增强
    用Opera Mobile调试手机版网页【转】
    mootools里选择器$,$$,$E,$ES等的区别
    Call to undefined function bcscale()
    阿里云服务器数据库配置
    阿里云Mysql重置密码
    window.open窗口关闭后刷新父窗口代码
  • 原文地址:https://www.cnblogs.com/lhh-boke/p/15064931.html
Copyright © 2020-2023  润新知