java对snowflake id生成实现如下:
import java.text.SimpleDateFormat;
import java.util.Date;
public class SnowflakeIdWorker {
/**
* Start time cut-off (1970-01-01)
*/
private final long twepoch = 0L;
/**
* Number of digits occupied by machine id
*/
private final long workerIdBits = 5L;
/**
* The number of digits occupied by the data identifier id
*/
private final long datacenterIdBits = 5L;
/**
* Supported maximum machine id, the result is 31 (this shift algorithm can quickly calculate the maximum decimal number represented by several bits of binary number)
*/
private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
/**
* Supported maximum data identifier id, resulting in 31
*/
private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
/**
* Number of digits in id of sequence
*/
private final long sequenceBits = 12L;
/**
* Machine ID moved 12 bits to the left
*/
private final long workerIdShift = sequenceBits;
/**
* Data id moved 17 bits to the left (12 + 5)
*/
private final long datacenterIdShift = sequenceBits + workerIdBits;
/**
* Time truncation moves 22 bits to the left (5 + 5 + 12)
*/
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
/**
* The mask of the generated sequence is 4095 (0b111111111111111111111 = 0xfff = 4095)
*/
private final long sequenceMask = -1L ^ (-1L << sequenceBits);
/**
* Work Machine ID (0-31)
*/
private long workerId;
/**
* Data Center ID (0-31)
*/
private long datacenterId;
/**
* Sequences in milliseconds (0-4095)
*/
private long sequence = 0L;
/**
* Time cut of last ID generation
*/
private long lastTimestamp = -1L;
public SnowflakeIdWorker(long workerId, long datacenterId) {
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
}
this.workerId = workerId;
this.datacenterId = datacenterId;
}
/**
* Get the next ID (this method is thread-safe)
*
* @return SnowflakeId
*/
public synchronized long nextId() {
long timestamp = timeGen();
//If the current time is less than the time stamp generated by the last ID, the system clock should throw an exception when it falls back.
if (timestamp < lastTimestamp) {
throw new RuntimeException(
String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
}
//If it is generated at the same time, the sequence in milliseconds is performed.
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & sequenceMask;
//Sequence overflow in milliseconds
if (sequence == 0) {
//Blocking to the next millisecond to get a new timestamp
timestamp = tilNextMillis(lastTimestamp);
}
}
//Time stamp change, sequence reset in milliseconds
else {
sequence = 0L;
}
//Time cut of last ID generation
lastTimestamp = timestamp;
//Shift and assemble 64-bit ID s together by operation or operation
return ((timestamp - twepoch) << timestampLeftShift) //
| (datacenterId << datacenterIdShift) //
| (workerId << workerIdShift) //
| sequence;
}
/**
* Block to the next millisecond until a new timestamp is obtained
*
* @param lastTimestamp Time cut of last ID generation
* @return Current timestamp
*/
protected long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
/**
* Returns the current time in milliseconds
*
* @return Current time (milliseconds)
*/
protected long timeGen() {
return System.currentTimeMillis();
}
public static void parseId(long id) {
long miliSecond = id >>> 22;
long shardId = (id & (0xFFF << 10)) >> 10;
System.err.println("Distributed id-"+id+"The generation time is:"+new SimpleDateFormat("yyyy-MM-dd").format(new Date(miliSecond)));
}
public static void main(String[] args) {
SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0);
for (int i = 0; i < 10; i++) {
long id = idWorker.nextId();
System.out.println(id);
parseId(id);
}
}
}
上述main执行完结果如下:
6714362529029554176
Distributed id-6714362529029554176The generation time is:2020-09-23
Distributed id-6714362529155383296The generation time is:2020-09-23
Distributed id-6714362529159577600The generation time is:2020-09-23
Distributed id-6714362529159577601The generation time is:2020-09-23
Distributed id-6714362529159577602The generation time is:2020-09-23
Distributed id-6714362529159577603The generation time is:2020-09-23
Distributed id-6714362529159577604The generation time is:2020-09-23
Distributed id-6714362529163771904The generation time is:2020-09-23
Distributed id-6714362529163771905The generation time is:2020-09-23
Distributed id-6714362529163771906The generation time is:2020-09-23
6714362529155383296
6714362529159577600
6714362529159577601
6714362529159577602
6714362529159577603
6714362529159577604
6714362529163771904
6714362529163771905
6714362529163771906
Process finished with exit code 0