# ID
# 雪花算法
/**
* <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
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,且无重复