zoukankan      html  css  js  c++  java
  • 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();
    }

    }
  • 相关阅读:
    epplus
    http://www.cmake.org/
    patheditor2
    emgu cv
    OpenCV
    Tesseract
    Blendar基金会
    安装服务windows,installutil
    R 软件
    历史为什么选择C语言?事实证明:暮年的C语言,依旧宝刀未老!
  • 原文地址:https://www.cnblogs.com/lhh-boke/p/15064931.html
Copyright © 2011-2022 走看看