package com.qianwen.core.sequence.sequence.impl; import com.qianwen.core.sequence.exception.SeqException; import com.qianwen.core.sequence.sequence.Sequence; public class SnowflakeSequence implements Sequence { private long workerId; private long datacenterId; private final long twepoch = 1514736000000L; private final long workerIdBits = 5; private final long datacenterIdBits = 5; private final long maxWorkerId = 31; private final long maxDatacenterId = 31; private final long sequenceBits = 12; private final long workerIdShift = 12; private final long datacenterIdShift = 17; private final long timestampLeftShift = 22; private final long sequenceMask = 4095; private long sequence = 0; private long lastTimestamp = -1; @Override // com.qianwen.core.sequence.sequence.Sequence public synchronized long nextValue() throws SeqException { long timestamp = timeGen(); if (timestamp < this.lastTimestamp) { throw new SeqException("[SnowflakeSequence-nextValue] 当前时间小于上次生成序列号的时间,时间被回退了,请确认服务器时间的设置."); } if (this.lastTimestamp == timestamp) { this.sequence = (this.sequence + 1) & 4095; if (this.sequence == 0) { timestamp = tilNextMillis(this.lastTimestamp); } } else { this.sequence = 0L; } this.lastTimestamp = timestamp; return ((timestamp - 1514736000000L) << 22) | (this.datacenterId << 17) | (this.workerId << 12) | this.sequence; } private long tilNextMillis(long lastTimestamp) { long timeGen = timeGen(); while (true) { long timestamp = timeGen; if (timestamp <= lastTimestamp) { timeGen = timeGen(); } else { return timestamp; } } } private long timeGen() { return System.currentTimeMillis(); } public void setWorkerId(long workerId) { if (workerId > 31) { throw new SeqException("[SnowflakeSequence-setWorkerId] workerId 不能大于31."); } this.workerId = workerId; } public void setDatacenterId(long datacenterId) { if (datacenterId > 31) { throw new SeqException("[SnowflakeSequence-setDatacenterId] datacenterId 不能大于31."); } this.datacenterId = datacenterId; } @Override // com.qianwen.core.sequence.sequence.Sequence public String nextNo() throws SeqException { return String.valueOf(nextValue()); } }