# ID

back

# 雪花算法

/**
 * <p>Title: SnowFlakeIdUtil</p>
 * <p>Description: 雪花算法获取分布式唯一ID</p>
 *
 * @author huting
 * @date 2019/9/9 13:38
 */
public class SnowFlakeIdUtil {
    /**
     * 起始的时间戳
     */
    private final static long START_STAMP = 592617600000L;
    /**
     * 序列号占用的位数
     */
    private final static long SEQUENCE_NUM = 12L;
    /**
     * 机器标识占用的位数
     */
    private final static long MACHINE_NUM = 5L;
    /**
     * 数据中心占用的位数
     */
    private final static long DATA_NUM = 5;
    /**
     * 每一位最大值
     */
    private final static long MAX_DATA = ~(-1L << DATA_NUM);
    private final static long MAX_MACHINE = ~(-1L << MACHINE_NUM);
    private final static long MAX_SEQUENCE = ~(-1L << SEQUENCE_NUM);

    /**
     * 每一部分左移
     */
    private final static long MACHINE_LEFT = SEQUENCE_NUM;
    private final static long DATA_LEFT = SEQUENCE_NUM+MACHINE_NUM;
    private final static long TIMESTAMP_LEFT = DATA_LEFT+DATA_NUM;

    private long dataId;
    private long machineId;
    private long sequence = 0L;
    private long lastStamp = -1L;

    public SnowFlakeIdUtil(long machineId,long dataId){
        if (dataId > MAX_DATA || dataId < 0){
            throw new IllegalArgumentException("数据ID不可为空或者小于零");
        }
        if (machineId > MAX_MACHINE || machineId < 0){
            throw new IllegalArgumentException("机器ID不可为空或者小于零");
        }
        this.machineId = machineId;
        this.dataId = dataId;
    }

    public synchronized long nextId(){
        long currMill = getNewStamp();
        if (currMill < lastStamp){
            throw new IllegalArgumentException("refused");
        }
        if (currMill == lastStamp){
            sequence = (sequence+1)&MAX_SEQUENCE;
            if (sequence == 0L){
                currMill = getNextMill();
            }
        } else {
            sequence = 0L;
        }

        lastStamp = currMill;
        return (currMill-START_STAMP)<<TIMESTAMP_LEFT|dataId<<DATA_LEFT|machineId<<MACHINE_LEFT|sequence;
    }

    private long getNextMill(){
        long mill = getNewStamp();
        while (mill <= this.lastStamp){
            mill = getNewStamp();
        }
        return mill;
    }

    private long getNewStamp(){
        return Clock.systemUTC().millis();
    }

    public static void main(String[] args) {
        SnowFlakeIdUtil snowFlakeIdUtil = new SnowFlakeIdUtil(10,12);
        Stopwatch stopwatch = Stopwatch.createStarted();
        for (int i = 0; i < 1000000; i++){
            System.out.println(snowFlakeIdUtil.nextId());
        }
        System.out.println(stopwatch.elapsed(TimeUnit.MILLISECONDS));
    }

}
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
90
91
92
93
94

1000000个消耗3775ms,且无重复