From e98a3e6fb6d49fc41b2dac4f1fcf8b8da5adeb0b Mon Sep 17 00:00:00 2001 From: ZhouXY108 Date: Sat, 9 Sep 2023 11:14:55 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../commons/util/SnowflakeIdGenerator.java | 124 +++++++++--------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/src/main/java/xyz/zhouxy/plusone/commons/util/SnowflakeIdGenerator.java b/src/main/java/xyz/zhouxy/plusone/commons/util/SnowflakeIdGenerator.java index 810eee7..2e74309 100644 --- a/src/main/java/xyz/zhouxy/plusone/commons/util/SnowflakeIdGenerator.java +++ b/src/main/java/xyz/zhouxy/plusone/commons/util/SnowflakeIdGenerator.java @@ -3,6 +3,7 @@ package xyz.zhouxy.plusone.commons.util; import java.util.concurrent.TimeUnit; import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; /** * Twitter_Snowflake @@ -11,20 +12,21 @@ import com.google.common.annotations.Beta; public class SnowflakeIdGenerator { // ==============================Fields=========================================== + /** 开始时间截(北京时间 2008/08/08 20:00) */ private static final long TWEPOCH = 1218196800000L; - /** 机器id所占的位数 */ + /** 机器 id 所占的位数 */ private static final long WORKER_ID_BITS = 5L; - /** 数据标识id所占的位数 */ + /** 数据标识 id 所占的位数 */ private static final long DATACENTER_ID_BITS = 5L; /** 支持的最大机器 id,结果是 31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */ - private static final long MAX_WORKER_ID = -1L ^ (-1L << WORKER_ID_BITS); + private static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS); /** 支持的最大数据标识 id,结果是 31 */ - private static final long MAX_DATACENTER_ID = -1L ^ (-1L << DATACENTER_ID_BITS); + private static final long MAX_DATACENTER_ID = ~(-1L << DATACENTER_ID_BITS); /** 序列在 id 中占的位数 */ private static final long SEQUENCE_BITS = 12L; @@ -39,13 +41,10 @@ public class SnowflakeIdGenerator { private static final long TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATACENTER_ID_BITS; /** 生成序列的掩码,这里为 4095 (0b111111111111=0xfff=4095) */ - private static final long SEQUENCE_MASK = -1L ^ (-1L << SEQUENCE_BITS); + private static final long SEQUENCE_MASK = ~(-1L << SEQUENCE_BITS); - /** 工作机器 ID (0~31) */ - private final long workerId; - - /** 数据中心 ID (0~31) */ - private final long datacenterId; + /** 数据中心 ID 和 工作机器 ID 偏移后的值 */ + private final long datacenterIdAndWorkerId; /** 毫秒内序列 (0~4095) */ private long sequence = 0L; @@ -53,83 +52,84 @@ public class SnowflakeIdGenerator { /** 上次生成 ID 的时间截 */ private long lastTimestamp = -1L; + /** 锁对象 */ + private final Object lock = new Object(); + // ==============================Constructors===================================== + /** * 构造函数 - * + * * @param workerId 工作ID (0~31) * @param datacenterId 数据中心ID (0~31) */ - public SnowflakeIdGenerator(long workerId, long datacenterId) { - if (workerId > MAX_WORKER_ID || workerId < 0) { - throw new IllegalArgumentException( - String.format("WorkerId can't be greater than %d or less than 0.", MAX_WORKER_ID)); - } - if (datacenterId > MAX_DATACENTER_ID || datacenterId < 0) { - throw new IllegalArgumentException( - String.format("DatacenterId can't be greater than %d or less than 0.", MAX_DATACENTER_ID)); - } - this.workerId = workerId; - this.datacenterId = datacenterId; + public SnowflakeIdGenerator(final long workerId, final long datacenterId) { + Preconditions.checkArgument((workerId > MAX_WORKER_ID || workerId < 0), + "WorkerId can't be greater than %s or less than 0.", MAX_WORKER_ID); + Preconditions.checkArgument((datacenterId > MAX_DATACENTER_ID || datacenterId < 0), + "DatacenterId can't be greater than %s or less than 0.", MAX_DATACENTER_ID); + this.datacenterIdAndWorkerId + = (datacenterId << DATACENTER_ID_SHIFT) | (workerId << WORKER_ID_SHIFT); } // ==============================Methods========================================== /** * 获得下一个ID (该方法是线程安全的) - * + * * @return SnowflakeId */ - public synchronized long nextId() { - long timestamp = timeGen(); + public long nextId() { + long timestamp; + synchronized (lock) { + timestamp = timeGen(); - // 发生了回拨,此刻时间小于上次发号时间 - if (timestamp < lastTimestamp) { - long offset = lastTimestamp - timestamp; - if (offset <= 5) { - // 时间偏差大小小于5ms,则等待两倍时间 - try { - TimeUnit.MILLISECONDS.sleep(offset << 1); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new IllegalStateException(e); - } - timestamp = timeGen(); - if (timestamp < lastTimestamp) { - // 还是小于,抛异常上报 + // 发生了回拨,此刻时间小于上次发号时间 + if (timestamp < lastTimestamp) { + long offset = lastTimestamp - timestamp; + if (offset <= 5) { + // 时间偏差大小小于5ms,则等待两倍时间 + try { + TimeUnit.MILLISECONDS.sleep(offset << 1); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new IllegalStateException(e); + } + timestamp = timeGen(); + if (timestamp < lastTimestamp) { + // 还是小于,抛异常上报 + throwClockBackwardsEx(lastTimestamp, timestamp); + } + } else { throwClockBackwardsEx(lastTimestamp, timestamp); } - } else { - throwClockBackwardsEx(lastTimestamp, timestamp); } - } - // 如果是同一时间生成的,则进行毫秒内序列 - if (lastTimestamp == timestamp) { - sequence = (sequence + 1) & SEQUENCE_MASK; - // 毫秒内序列溢出 - if (sequence == 0) { - // 阻塞到下一个毫秒,获得新的时间戳 - timestamp = tilNextMillis(lastTimestamp); + // 如果是同一时间生成的,则进行毫秒内序列 + if (lastTimestamp == timestamp) { + sequence = (sequence + 1) & SEQUENCE_MASK; + // 毫秒内序列溢出 + if (sequence == 0) { + // 阻塞到下一个毫秒,获得新的时间戳 + timestamp = tilNextMillis(lastTimestamp); + } + } + // 时间戳改变,毫秒内序列重置 + else { + sequence = 0L; } - } - // 时间戳改变,毫秒内序列重置 - else { - sequence = 0L; - } - // 上次生成 ID 的时间截 - lastTimestamp = timestamp; + // 上次生成 ID 的时间截 + lastTimestamp = timestamp; + + } // 移位并通过或运算拼到一起组成64位的ID - return ((timestamp - TWEPOCH) << TIMESTAMP_LEFT_SHIFT) // - | (datacenterId << DATACENTER_ID_SHIFT) // - | (workerId << WORKER_ID_SHIFT) // - | sequence; + return ((timestamp - TWEPOCH) << TIMESTAMP_LEFT_SHIFT) | datacenterIdAndWorkerId | sequence; } /** * 阻塞到下一个毫秒,直到获得新的时间戳 - * + * * @param lastTimestamp 上次生成ID的时间截 * @return 当前时间戳 */ @@ -143,7 +143,7 @@ public class SnowflakeIdGenerator { /** * 返回以毫秒为单位的当前时间 - * + * * @return 当前时间(毫秒) */ protected long timeGen() {