package com.doumee.core.utils;
|
|
import org.apache.logging.log4j.util.Strings;
|
|
import java.util.UUID;
|
|
/**
|
* A utility to generate id using various strategies.
|
*
|
* @author Guang YANG
|
* @version 1.0
|
*/
|
public class ID {
|
|
private static final SnowflakeIdGenerator snowflake = new SnowflakeIdGenerator(0);
|
|
|
|
/**
|
* Generate a random guid string of 32 byte.
|
*/
|
public static String nextGUID() {
|
return UUID.randomUUID().toString().replace("-", Strings.EMPTY).toUpperCase();
|
}
|
|
/**
|
* Generate a random uuid string of 36 byte.
|
*/
|
public static String nextUUID() {
|
return UUID.randomUUID().toString();
|
}
|
|
/**
|
* Generate a long number of 20 bit which is monotonically increasing by each call.
|
*/
|
public static long nextSnowflakeId() {
|
return snowflake.nextId();
|
}
|
|
public static class SnowflakeIdGenerator {
|
|
private final long workerIdBits = 10L;
|
private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
|
private final long sequenceBits = 12L;
|
private final long workerIdShift = sequenceBits;
|
private final long timestampLeftShift = sequenceBits + workerIdBits;
|
private final long sequenceMask = -1L ^ (-1L << sequenceBits);
|
|
private long workerId;
|
private long sequence = 0L;
|
private long lastTimestamp = -1L;
|
|
public SnowflakeIdGenerator(long workerId) {
|
if (workerId > maxWorkerId || workerId < 0) {
|
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
|
}
|
this.workerId = workerId;
|
}
|
|
public synchronized long nextId() {
|
long timestamp = System.currentTimeMillis();
|
if (timestamp < lastTimestamp) {
|
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
|
}
|
if (lastTimestamp == timestamp) {
|
sequence = (sequence + 1) & sequenceMask;
|
if (sequence == 0) {
|
timestamp = tilNextMillis(lastTimestamp);
|
}
|
} else {
|
sequence = 0L;
|
}
|
|
lastTimestamp = timestamp;
|
|
return (timestamp << timestampLeftShift) | (workerId << workerIdShift) | sequence;
|
}
|
|
protected long tilNextMillis(long lastTimestamp) {
|
long timestamp = System.currentTimeMillis();
|
while (timestamp <= lastTimestamp) {
|
timestamp = System.currentTimeMillis();
|
}
|
return timestamp;
|
}
|
|
}
|
|
}
|