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());
}
}