Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 98c9f09

Browse files
committed
add SnowflakeIdWorker
1 parent 8cfa681 commit 98c9f09

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package com.github.myibu.algorithm.id;
2+
3+
/**
4+
* Twitter Snowflake
5+
* see <a href="https://github.com/twitter-archive/snowflake/blob/scala_28/src/main/scala/com/twitter/service/snowflake/IdWorker.scala">snowflake's IdWorker</a>
6+
* @author myibu
7+
* Created on 2022年10月12日
8+
*/
9+
public class SnowflakeIdWorker {
10+
private final static long twepoch = 1598598185157L;
11+
12+
private long sequence = 0L;
13+
private final static long workerIdBits = 5L;
14+
private final static long datacenterIdBits = 5L;
15+
private final static long maxWorkerId = -1L ^ (-1L << workerIdBits);
16+
private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
17+
private final static long sequenceBits = 12L;
18+
19+
private final static long workerIdShift = sequenceBits;
20+
private final static long datacenterIdShift = sequenceBits + workerIdBits;
21+
private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
22+
private final static long sequenceMask = -1L ^ (-1L << sequenceBits);
23+
24+
private long lastTimestamp = -1L;
25+
26+
private final long workerId;
27+
private final long datacenterId;
28+
29+
public SnowflakeIdWorker(long workerId, long datacenterId) {
30+
if (workerId > maxWorkerId || workerId < 0) {
31+
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
32+
}
33+
if (datacenterId > maxDatacenterId || datacenterId < 0) {
34+
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
35+
}
36+
this.workerId = workerId;
37+
this.datacenterId = datacenterId;
38+
}
39+
40+
public long getWorkerId() {
41+
return workerId;
42+
}
43+
44+
public long getDatacenterId() {
45+
return datacenterId;
46+
}
47+
48+
public long getTimestamp() {
49+
return System.currentTimeMillis();
50+
}
51+
52+
public synchronized long nextId() {
53+
long timestamp = timeGen();
54+
55+
if (lastTimestamp == timestamp) {
56+
sequence = (sequence + 1) & sequenceMask;
57+
if (sequence == 0) {
58+
timestamp = tilNextMillis(lastTimestamp);
59+
}
60+
} else {
61+
sequence = 0L;
62+
}
63+
64+
if (timestamp < lastTimestamp) {
65+
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
66+
}
67+
68+
lastTimestamp = timestamp;
69+
70+
return ((timestamp - twepoch) << timestampLeftShift)
71+
| (datacenterId << datacenterIdShift)
72+
| (workerId << workerIdShift)
73+
| sequence;
74+
}
75+
76+
protected long tilNextMillis(long lastTimestamp) {
77+
long timestamp = timeGen();
78+
while (timestamp <= lastTimestamp) {
79+
timestamp = timeGen();
80+
}
81+
return timestamp;
82+
}
83+
84+
protected long timeGen() {
85+
return System.currentTimeMillis();
86+
}
87+
}

‎src/test/java/com/github/myibu/algorithm/AlgorithmTest.java‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.github.myibu.algorithm.hash.MurmurHash2;
1010
import com.github.myibu.algorithm.hash.SHA256;
1111
import com.github.myibu.algorithm.hash.SipHash;
12+
import com.github.myibu.algorithm.id.SnowflakeIdWorker;
1213
import com.github.myibu.algorithm.random.LinearCongruentialRandom;
1314
import com.github.myibu.algorithm.random.MersenneTwisterRandom;
1415
import com.github.myibu.algorithm.random.Random;
@@ -379,4 +380,13 @@ public void testBitsEncoder() {
379380
Assert.assertEquals(-2, Bits.Decoder.decodeZigzagValue(3));
380381
Assert.assertEquals(-1, Bits.Decoder.decodeZigzagValue(1));
381382
}
383+
384+
@Test
385+
public void testSnowflakeIdWorker() {
386+
SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0);
387+
for (int i = 0; i < 1000; i++) {
388+
long id = idWorker.nextId();
389+
System.out.println(id);
390+
}
391+
}
382392
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /