天天看點

生成唯一id算法java_Java唯一Id生成器基于雪花算法

Java唯一Id生成器基于雪花算法

java代碼

package cn.pconline.common.utils;

import lombok.extern.slf4j.Slf4j;

@Slf4j

public class SnowFlakeUtil {

private static SnowFlakeUtil flowIdWorker = new SnowFlakeUtil(1);

private final long id;

private final long epoch = 1524291141010L;

private final long workerIdBits = 10L;

private final long maxWorkerId = -1L ^ -1L << this.workerIdBits;

private final long sequenceBits = 12L;

private final long workerIdShift = this.sequenceBits;

private final long timestampLeftShift = this.sequenceBits + this.workerIdBits;

private final long sequenceMask = -1L ^ -1L << this.sequenceBits;

private long sequence = 0L;

private long lastTimestamp = -1L;

private SnowFlakeUtil(long id) {

if (id > this.maxWorkerId || id < 0) {

throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", this.maxWorkerId));

}

this.id = id;

}

public static SnowFlakeUtil getFlowIdInstance() {

return flowIdWorker;

}

private static long timeGen() {

return System.currentTimeMillis();

}

public static void main(String[] args) {

for (int i = 0; i < 100; i++) {

SnowFlakeUtil snowFlakeUtil = SnowFlakeUtil.getFlowIdInstance();

System.out.println(snowFlakeUtil.nextId());

}

}

public synchronized long nextId() {

long timestamp = timeGen();

if (this.lastTimestamp == timestamp) {

//如果上一個timestamp與新産生的相等,則sequence加一(0-4095循環); 對新的timestamp,sequence從0開始

this.sequence = this.sequence + 1 & this.sequenceMask;

if (this.sequence == 0) {

// 重新生成timestamp

timestamp = this.tilNextMillis(this.lastTimestamp);

}

} else {

this.sequence = 0;

}

if (timestamp < this.lastTimestamp) {

log.error(String.format("clock moved backwards.Refusing to generate id for %d milliseconds", (this.lastTimestamp - timestamp)));

return -1;

}

this.lastTimestamp = timestamp;

return timestamp - this.epoch << this.timestampLeftShift | this.id << this.workerIdShift | this.sequence;

}

private long tilNextMillis(long lastTimestamp) {

long timestamp = timeGen();

while (timestamp <= lastTimestamp) {

timestamp = timeGen();

}

return timestamp;

}

}