SnowflakeIdGenerator.java 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. package com.zhentao.utils;
  2. import java.time.LocalDateTime;
  3. import java.time.ZoneOffset;
  4. public class SnowflakeIdGenerator {
  5. // 基础配置(Java 8+)
  6. private static final long EPOCH = 1288834974657L; // 2010-11-04 00:00:00 UTC
  7. private static final int DATACENTER_ID_BITS = 5;
  8. private static final int WORKER_ID_BITS = 5;
  9. private static final int SEQUENCE_BITS = 12;
  10. // 位运算掩码
  11. private static final long DATACENTER_ID_MASK = (1L << DATACENTER_ID_BITS) - 1;
  12. private static final long WORKER_ID_MASK = (1L << WORKER_ID_BITS) - 1;
  13. private static final long SEQUENCE_MASK = (1L << SEQUENCE_BITS) - 1;
  14. // 位移偏移量
  15. private static final int WORKER_ID_SHIFT = SEQUENCE_BITS;
  16. private static final int DATACENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;
  17. private static final int TIMESTAMP_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATACENTER_ID_BITS;
  18. private final long datacenterId;
  19. private final long workerId;
  20. private long sequence = 0L;
  21. private long lastTimestamp = -1L;
  22. private final Object lock = new Object();
  23. public SnowflakeIdGenerator(long datacenterId, long workerId) {
  24. if ((datacenterId & DATACENTER_ID_MASK) != datacenterId) {
  25. throw new IllegalArgumentException("DataCenter ID 必须在 0-31 之间");
  26. }
  27. if ((workerId & WORKER_ID_MASK) != workerId) {
  28. throw new IllegalArgumentException("Worker ID 必须在 0-31 之间");
  29. }
  30. this.datacenterId = datacenterId;
  31. this.workerId = workerId;
  32. }
  33. public synchronized long nextId() {
  34. long currentTimestamp = timeGen();
  35. if (currentTimestamp < lastTimestamp) {
  36. throw new IllegalStateException(
  37. String.format("时钟回退 %d 毫秒,禁止生成ID(上次: %d,当前: %d)",
  38. lastTimestamp - currentTimestamp, lastTimestamp, currentTimestamp));
  39. }
  40. if (currentTimestamp == lastTimestamp) {
  41. sequence = (sequence + 1) & SEQUENCE_MASK;
  42. if (sequence == 0) {
  43. currentTimestamp = waitNextMillis(lastTimestamp);
  44. }
  45. } else {
  46. sequence = 0;
  47. }
  48. lastTimestamp = currentTimestamp;
  49. return ((currentTimestamp - EPOCH) << TIMESTAMP_SHIFT) |
  50. (datacenterId << DATACENTER_ID_SHIFT) |
  51. (workerId << WORKER_ID_SHIFT) |
  52. sequence;
  53. }
  54. private long waitNextMillis(long lastTimestamp) {
  55. long timestamp = timeGen();
  56. while (timestamp <= lastTimestamp) {
  57. timestamp = System.currentTimeMillis(); // 改用更可靠的时间源
  58. }
  59. return timestamp;
  60. }
  61. private long timeGen() {
  62. return System.currentTimeMillis();
  63. }
  64. // 添加 parseId 方法
  65. public static SnowflakeMeta parseId(long snowflakeId) {
  66. long sequence = snowflakeId & SEQUENCE_MASK;
  67. long workerId = (snowflakeId >> WORKER_ID_SHIFT) & WORKER_ID_MASK;
  68. long datacenterId = (snowflakeId >> DATACENTER_ID_SHIFT) & DATACENTER_ID_MASK;
  69. long timestamp = (snowflakeId >> TIMESTAMP_SHIFT) + EPOCH;
  70. return new SnowflakeMeta(
  71. timestamp,
  72. datacenterId,
  73. workerId,
  74. sequence,
  75. LocalDateTime.ofEpochSecond(timestamp / 1000, 0, ZoneOffset.ofHours(8))
  76. );
  77. }
  78. public static Long getSnowId(){
  79. SnowflakeIdGenerator generator=new SnowflakeIdGenerator(1,1);
  80. Long id=generator.nextId();
  81. SnowflakeMeta meta=SnowflakeIdGenerator.parseId(id);
  82. return id;
  83. }
  84. // ---------------- 修复:添加完整的getter方法 ----------------
  85. public static class SnowflakeMeta {
  86. private final long timestamp;
  87. private final long datacenterId;
  88. private final long workerId;
  89. private final long sequence;
  90. private final LocalDateTime dateTime;
  91. public SnowflakeMeta(long timestamp, long datacenterId, long workerId, long sequence, LocalDateTime dateTime) {
  92. this.timestamp = timestamp;
  93. this.datacenterId = datacenterId;
  94. this.workerId = workerId;
  95. this.sequence = sequence;
  96. this.dateTime = dateTime;
  97. }
  98. // 显式定义getter(修复爆红)
  99. public long getTimestamp() {
  100. return timestamp;
  101. }
  102. public long getDatacenterId() {
  103. return datacenterId;
  104. }
  105. public long getWorkerId() {
  106. return workerId;
  107. }
  108. public long getSequence() {
  109. return sequence;
  110. }
  111. public LocalDateTime getDateTime() {
  112. return dateTime;
  113. }
  114. }
  115. }