Skip to content

Commit 2e21974

Browse files
committed
add snowId
1 parent 15ef0f4 commit 2e21974

File tree

3 files changed

+156
-0
lines changed

3 files changed

+156
-0
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.learnjava.concurent;
2+
3+
/**
4+
* @author lhy
5+
* @date 2021/7/27
6+
*/
7+
public class SnowIdDemo {
8+
public static void main(String[] args) {
9+
// 通过雪花秀算法获取分布式id
10+
System.out.println(SnowIdUtils.uniqueLongHex());
11+
}
12+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package com.learnjava.concurent;
2+
3+
/**
4+
* @author lhy
5+
* @date 2021/7/27
6+
*/
7+
public class SnowIdUtils {
8+
/**
9+
* 私有的 静态内部类
10+
*/
11+
private static class SnowFlake {
12+
13+
/**
14+
* 内部类对象(单例模式)
15+
*/
16+
private static final SnowIdUtils.SnowFlake SNOW_FLAKE = new SnowIdUtils.SnowFlake();
17+
/**
18+
* 起始的时间戳
19+
*/
20+
private final long START_TIMESTAMP = 1609464335121L;
21+
/**
22+
* 序列号占用位数
23+
*/
24+
private final long SEQUENCE_BIT = 12;
25+
/**
26+
* 机器标识占用位数
27+
*/
28+
private final long MACHINE_BIT = 10;
29+
/**
30+
* 时间戳位移位数
31+
*/
32+
private final long TIMESTAMP_LEFT = SEQUENCE_BIT + MACHINE_BIT;
33+
/**
34+
* 最大序列号 (4095)
35+
*/
36+
private final long MAX_SEQUENCE = ~(-1L << SEQUENCE_BIT);
37+
/**
38+
* 最大机器编号 (1023)
39+
*/
40+
private final long MAX_MACHINE_ID = ~(-1L << MACHINE_BIT);
41+
/**
42+
* 生成id机器标识部分
43+
*/
44+
private long machineIdPart;
45+
/**
46+
* 序列号
47+
*/
48+
private long sequence = 0L;
49+
/**
50+
* 上一次时间戳
51+
*/
52+
private long lastStamp = -1L;
53+
54+
/**
55+
* 构造函数初始化机器编码
56+
*/
57+
private SnowFlake() {
58+
// String ip = instance.getDockerIp().replace(".", "");
59+
// 模拟获取机器节点ip
60+
String ip = "127.0.0.1";
61+
long localIp = Long.valueOf(ip.replace(".", ""));
62+
machineIdPart = (localIp & MAX_MACHINE_ID) << SEQUENCE_BIT;
63+
}
64+
/**
65+
* 获取雪花ID
66+
*/
67+
public synchronized long nextId() {
68+
long currentStamp = timeGen();
69+
while (currentStamp < lastStamp) {
70+
throw new RuntimeException(String.format("时钟已经回拨. Refusing to generate id for %d milliseconds", lastStamp - currentStamp));
71+
}
72+
if (currentStamp == lastStamp) {
73+
sequence = (sequence + 1) & MAX_SEQUENCE;
74+
if (sequence == 0) {
75+
currentStamp = getNextMill();
76+
}
77+
} else {
78+
sequence = 0L;
79+
}
80+
lastStamp = currentStamp;
81+
return (currentStamp - START_TIMESTAMP) << TIMESTAMP_LEFT | machineIdPart | sequence;
82+
}
83+
/**
84+
* 阻塞到下一个毫秒,直到获得新的时间戳
85+
*/
86+
private long getNextMill() {
87+
long mill = timeGen();
88+
//
89+
while (mill <= lastStamp) {
90+
mill = timeGen();
91+
}
92+
return mill;
93+
}
94+
/**
95+
* 返回以毫秒为单位的当前时间
96+
*/
97+
protected long timeGen() {
98+
return System.currentTimeMillis();
99+
}
100+
}
101+
102+
/**
103+
* 获取long类型雪花ID
104+
*/
105+
public static long uniqueLong() {
106+
return SnowIdUtils.SnowFlake.SNOW_FLAKE.nextId();
107+
}
108+
/**
109+
* 获取String类型雪花ID
110+
*/
111+
public static String uniqueLongHex() {
112+
return String.format("%016X", uniqueLong());
113+
}
114+
}

JdkLearn/src/main/java/com/learnjava/optimization/OptimizeDemo.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.HashMap;
44
import java.util.Map;
5+
import java.util.concurrent.ConcurrentHashMap;
56

67
/**
78
*
@@ -14,6 +15,9 @@ public class OptimizeDemo {
1415
public static void main(String[] args) {
1516
Map<String, Integer> map = new HashMap<>();
1617
mergeData(map);
18+
19+
Map<String, Integer> concurrentMap = new ConcurrentHashMap<>();
20+
concurrentMergeData(concurrentMap);
1721
}
1822

1923
/**
@@ -34,7 +38,33 @@ public static void mergeData(Map<String, Integer> map) {
3438
Integer mapValue = map.get(key);
3539
if (null != mapValue) {
3640
mapValue += value;
41+
} else {
42+
mapValue = value;
3743
}
3844
map.put(key, mapValue);
3945
}
46+
47+
/**
48+
* 针对mergeData里map的put操作,在并发情况下会存在put的时候,以及有其他线程已经put成功了,导致线程不安全,
49+
* 所以需要使用并发集合列的putIfAbsent方法
50+
* @param map
51+
*/
52+
public static void concurrentMergeData(Map<String, Integer> map) {
53+
String key = "mapKey";
54+
int value = 1;
55+
Integer mapValue = map.get(key);
56+
if (null != mapValue) {
57+
mapValue += value;
58+
} else {
59+
mapValue = value;
60+
}
61+
map.putIfAbsent(key, mapValue);
62+
63+
// computeIfAbsent方法对map中的key只进行重新计算,如果不存在这个key,则添加到map中
64+
map.computeIfAbsent(key, (k) -> {
65+
// 其他计算
66+
int a = 1, b = 2;
67+
return a + b;
68+
});
69+
}
4070
}

0 commit comments

Comments
 (0)