jiangping
2024-05-10 dab5db84055a7f6a8fea3b61099d85d34ea7a706
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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;
    }
 
  }
 
}