forked from plusone/plusone-commons
完成 ID 生成器的单元测试
parent
26bae49d47
commit
62e3769802
|
@ -1,6 +1,6 @@
|
||||||
[ ] 未开始测试 - 13 (19.40%)
|
[ ] 未开始测试 - 10 (14.93%)
|
||||||
[-] 测试未完成 - 9 (13.43%)
|
[-] 测试未完成 - 9 (13.43%)
|
||||||
[Y] 测试完成 - 24 (35.82%)
|
[Y] 测试完成 - 27 (40.30%)
|
||||||
[x] 无需测试 - 21 (31.34%)
|
[x] 无需测试 - 21 (31.34%)
|
||||||
|
|
||||||
xyz.zhouxy.plusone.commons
|
xyz.zhouxy.plusone.commons
|
||||||
|
@ -87,12 +87,12 @@ xyz.zhouxy.plusone.commons
|
||||||
DateTimeTools.java [-]
|
DateTimeTools.java [-]
|
||||||
Enumeration.java [Y]
|
Enumeration.java [Y]
|
||||||
EnumTools.java [Y]
|
EnumTools.java [Y]
|
||||||
IdGenerator.java [ ]
|
IdGenerator.java [Y]
|
||||||
IdWorker.java [ ]
|
IdWorker.java [Y]
|
||||||
Numbers.java [Y]
|
Numbers.java [Y]
|
||||||
OptionalTools.java [Y]
|
OptionalTools.java [Y]
|
||||||
RandomTools.java [ ]
|
RandomTools.java [ ]
|
||||||
RegexTools.java [ ]
|
RegexTools.java [ ]
|
||||||
SnowflakeIdGenerator.java [ ]
|
SnowflakeIdGenerator.java [Y]
|
||||||
StringTools.java [Y]
|
StringTools.java [Y]
|
||||||
TreeBuilder.java [Y]
|
TreeBuilder.java [Y]
|
||||||
|
|
|
@ -64,9 +64,6 @@ public class SnowflakeIdGenerator {
|
||||||
/** 上次生成 ID 的时间截 */
|
/** 上次生成 ID 的时间截 */
|
||||||
private long lastTimestamp = -1L;
|
private long lastTimestamp = -1L;
|
||||||
|
|
||||||
/** 锁对象 */
|
|
||||||
private final Object lock = new Object();
|
|
||||||
|
|
||||||
// ==============================Constructors=====================================
|
// ==============================Constructors=====================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -90,51 +87,47 @@ public class SnowflakeIdGenerator {
|
||||||
*
|
*
|
||||||
* @return SnowflakeId
|
* @return SnowflakeId
|
||||||
*/
|
*/
|
||||||
public long nextId() {
|
public synchronized long nextId() {
|
||||||
long timestamp;
|
long timestamp = timeGen();
|
||||||
synchronized (lock) {
|
|
||||||
timestamp = timeGen();
|
|
||||||
|
|
||||||
// 发生了回拨,此刻时间小于上次发号时间
|
// 发生了回拨,此刻时间小于上次发号时间
|
||||||
if (timestamp < lastTimestamp) {
|
if (timestamp < lastTimestamp) {
|
||||||
long offset = lastTimestamp - timestamp;
|
long offset = lastTimestamp - timestamp;
|
||||||
if (offset <= 5) {
|
if (offset <= 5) {
|
||||||
// 时间偏差大小小于5ms,则等待两倍时间
|
// 时间偏差大小小于5ms,则等待两倍时间
|
||||||
try {
|
try {
|
||||||
TimeUnit.MILLISECONDS.sleep(offset << 1);
|
TimeUnit.MILLISECONDS.sleep(offset << 1);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
throw new IllegalStateException(e);
|
throw new IllegalStateException(e);
|
||||||
}
|
}
|
||||||
timestamp = timeGen();
|
timestamp = timeGen();
|
||||||
if (timestamp < lastTimestamp) {
|
if (timestamp < lastTimestamp) {
|
||||||
// 还是小于,抛异常上报
|
// 还是小于,抛异常上报
|
||||||
throwClockBackwardsEx(lastTimestamp, timestamp);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throwClockBackwardsEx(lastTimestamp, timestamp);
|
throwClockBackwardsEx(lastTimestamp, timestamp);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
throwClockBackwardsEx(lastTimestamp, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果是同一时间生成的,则进行毫秒内序列
|
|
||||||
if (lastTimestamp == timestamp) {
|
|
||||||
sequence = (sequence + 1) & SEQUENCE_MASK;
|
|
||||||
// 毫秒内序列溢出
|
|
||||||
if (sequence == 0) {
|
|
||||||
// 阻塞到下一个毫秒,获得新的时间戳
|
|
||||||
timestamp = tilNextMillis(lastTimestamp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 时间戳改变,毫秒内序列重置
|
|
||||||
else {
|
|
||||||
sequence = 0L;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 上次生成 ID 的时间截
|
|
||||||
lastTimestamp = timestamp;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果是同一时间生成的,则进行毫秒内序列
|
||||||
|
if (lastTimestamp == timestamp) {
|
||||||
|
sequence = (sequence + 1) & SEQUENCE_MASK;
|
||||||
|
// 毫秒内序列溢出
|
||||||
|
if (sequence == 0) {
|
||||||
|
// 阻塞到下一个毫秒,获得新的时间戳
|
||||||
|
timestamp = tilNextMillis(lastTimestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 时间戳改变,毫秒内序列重置
|
||||||
|
else {
|
||||||
|
sequence = 0L;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上次生成 ID 的时间截
|
||||||
|
lastTimestamp = timestamp;
|
||||||
|
|
||||||
// 移位并通过或运算拼到一起组成64位的ID
|
// 移位并通过或运算拼到一起组成64位的ID
|
||||||
return ((timestamp - TWEPOCH) << TIMESTAMP_LEFT_SHIFT) | datacenterIdAndWorkerId | sequence;
|
return ((timestamp - TWEPOCH) << TIMESTAMP_LEFT_SHIFT) | datacenterIdAndWorkerId | sequence;
|
||||||
}
|
}
|
||||||
|
|
|
@ -925,9 +925,10 @@ public class AssertToolsTests {
|
||||||
|
|
||||||
// #region - Condition
|
// #region - Condition
|
||||||
|
|
||||||
|
static final class MyException extends RuntimeException {}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testCheckCondition() {
|
void testCheckCondition() {
|
||||||
class MyException extends RuntimeException {}
|
|
||||||
|
|
||||||
AssertTools.checkCondition(true, MyException::new);
|
AssertTools.checkCondition(true, MyException::new);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
package xyz.zhouxy.plusone.commons.util;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.ConcurrentHashSet;
|
||||||
|
|
||||||
|
public class IdGeneratorTests {
|
||||||
|
|
||||||
|
final ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10,
|
||||||
|
0L, TimeUnit.MILLISECONDS,
|
||||||
|
new LinkedBlockingQueue<Runnable>());
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSnowflakeIdGenerator() { // NOSONAR
|
||||||
|
final SnowflakeIdGenerator snowflake = new SnowflakeIdGenerator(0, 0);
|
||||||
|
final Set<Long> ids = new ConcurrentHashSet<>();
|
||||||
|
for (int i = 0; i < 10000; i++) {
|
||||||
|
executor.execute(() -> {
|
||||||
|
for (int j = 0; j < 50000; j++) {
|
||||||
|
if (false == ids.add(snowflake.nextId())) {
|
||||||
|
throw new RuntimeException("重复ID!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testIdWorker() { // NOSONAR
|
||||||
|
final IdWorker idWorker = new IdWorker(0L);
|
||||||
|
final Set<Long> ids = new ConcurrentHashSet<>();
|
||||||
|
for (int i = 0; i < 10000; i++) {
|
||||||
|
executor.execute(() -> {
|
||||||
|
for (int j = 0; j < 50000; j++) {
|
||||||
|
if (false == ids.add(idWorker.nextId())) {
|
||||||
|
throw new RuntimeException("重复ID!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
executor.execute(() -> {
|
||||||
|
for (int j = 0; j < 50000; j++) {
|
||||||
|
if (false == ids.add(IdGenerator.nextSnowflakeId(0))) {
|
||||||
|
throw new RuntimeException("重复ID!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testToSimpleString() {
|
||||||
|
UUID id = UUID.randomUUID();
|
||||||
|
assertEquals(id.toString().replaceAll("-", ""),
|
||||||
|
IdGenerator.toSimpleString(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue