自己动手系列-雪花算法

211 阅读1分钟

package algorithm.snow;

import java.text.SimpleDateFormat; import java.util.HashSet;

/**

  • @description: twitter的snowflake算法 -- java实现
  • @author: Ksssss(chenlin @ hoolai.com)
  • @time: 2020-06-09 17:41 */

public class SnowFlake { //开始时间戳 private static final long START_TIMESTAMP = 1591704003000l; //服务器id长度 private static final int SERVER_ID_LEN = 6; //分区id长度 private static final int CLIENT_ID_LEN = 6; //玩家id长度 private static final int PLAYER_ID_LEN = 12;

private static final int MAX_SERVER_ID = (-1 ^ (-1 << SERVER_ID_LEN));
private static final int MAX_CLIENT_ID = (-1 ^ (-1 << CLIENT_ID_LEN));
private static final int MAX_PLAYER_ID = (-1 ^ (-1 << PLAYER_ID_LEN));
private final int serverId;
private final int clientId;
private long lastTimeStamp;
private int playerId;

public SnowFlake(int serverId, int clientId) {
    if (serverId > MAX_SERVER_ID || serverId < 0) {
        throw new IllegalArgumentException("serverId out of range or serverId < 0");
    }
    this.serverId = serverId;
    if (clientId > MAX_CLIENT_ID || clientId < 0) {
        throw new IllegalArgumentException("clientId out of range or clientId < 0");
    }
    this.clientId = clientId;
}

public synchronized long nextId() {
    long curTimeStamp = getCurTimeStamp();
    if (curTimeStamp < lastTimeStamp) {
        throw new RuntimeException("refusing to generate id");
    }
    if (curTimeStamp == lastTimeStamp) {
        playerId++;
        if (playerId > MAX_PLAYER_ID) {
            playerId = 0;
        }
        curTimeStamp = getNextTimeStamp();
    } else {
        playerId = 0;
    }
    this.lastTimeStamp = curTimeStamp;
    return curTimeStamp - START_TIMESTAMP << SERVER_ID_LEN + CLIENT_ID_LEN + PLAYER_ID_LEN |
            serverId << CLIENT_ID_LEN + PLAYER_ID_LEN |
            clientId << PLAYER_ID_LEN |
            playerId;
}

private long getNextTimeStamp() {
    long currentTimeStamp = getCurTimeStamp();
    while (currentTimeStamp <= lastTimeStamp) {
        currentTimeStamp = getCurTimeStamp();
    }
    return currentTimeStamp;
}

private long getCurTimeStamp() {
    return System.currentTimeMillis();
}

public static void main(String[] args) {
    HashSet<Long> set = new HashSet();
    SnowFlake snowFlake = new SnowFlake(31, 1);
    for (int i = 0; i < 1 << 12; i++) {
        set.add(snowFlake.nextId());
    }
    System.out.println(set.size());
}

}