mirror of
				https://gitee.com/dromara/hutool.git
				synced 2025-11-01 00:46:56 +08:00 
			
		
		
		
	fix code
This commit is contained in:
		| @@ -15,7 +15,6 @@ package org.dromara.hutool.core.data.id; | |||||||
| import org.dromara.hutool.core.date.SystemClock; | import org.dromara.hutool.core.date.SystemClock; | ||||||
| import org.dromara.hutool.core.lang.Assert; | import org.dromara.hutool.core.lang.Assert; | ||||||
| import org.dromara.hutool.core.lang.tuple.Pair; | import org.dromara.hutool.core.lang.tuple.Pair; | ||||||
| import org.dromara.hutool.core.text.StrUtil; |  | ||||||
| import org.dromara.hutool.core.util.RandomUtil; | import org.dromara.hutool.core.util.RandomUtil; | ||||||
|  |  | ||||||
| import java.io.Serializable; | import java.io.Serializable; | ||||||
| @@ -53,11 +52,6 @@ public class Snowflake implements Serializable { | |||||||
| 	 * 默认的起始时间,为Thu, 04 Nov 2010 01:42:54 GMT | 	 * 默认的起始时间,为Thu, 04 Nov 2010 01:42:54 GMT | ||||||
| 	 */ | 	 */ | ||||||
| 	public static long DEFAULT_TWEPOCH = 1288834974657L; | 	public static long DEFAULT_TWEPOCH = 1288834974657L; | ||||||
| 	/** |  | ||||||
| 	 * 默认回拨时间,2S |  | ||||||
| 	 */ |  | ||||||
| 	public static long DEFAULT_TIME_OFFSET = 2000L; |  | ||||||
|  |  | ||||||
| 	private static final long WORKER_ID_BITS = 5L; | 	private static final long WORKER_ID_BITS = 5L; | ||||||
| 	// 最大支持机器节点数0~31,一共32个 | 	// 最大支持机器节点数0~31,一共32个 | ||||||
| 	@SuppressWarnings({"PointlessBitwiseExpression", "FieldCanBeLocal"}) | 	@SuppressWarnings({"PointlessBitwiseExpression", "FieldCanBeLocal"}) | ||||||
| @@ -84,10 +78,6 @@ public class Snowflake implements Serializable { | |||||||
| 	private final long workerId; | 	private final long workerId; | ||||||
| 	private final long dataCenterId; | 	private final long dataCenterId; | ||||||
| 	private final boolean useSystemClock; | 	private final boolean useSystemClock; | ||||||
| 	/** |  | ||||||
| 	 * 允许的时钟回拨毫秒数 |  | ||||||
| 	 */ |  | ||||||
| 	private final long timeOffset; |  | ||||||
| 	/** | 	/** | ||||||
| 	 * 当在低频模式下时,序号始终为0,导致生成ID始终为偶数<br> | 	 * 当在低频模式下时,序号始终为0,导致生成ID始终为偶数<br> | ||||||
| 	 * 此属性用于限定一个随机上限,在不同毫秒下生成序号时,给定一个随机数,避免偶数问题。<br> | 	 * 此属性用于限定一个随机上限,在不同毫秒下生成序号时,给定一个随机数,避免偶数问题。<br> | ||||||
| @@ -146,20 +136,9 @@ public class Snowflake implements Serializable { | |||||||
| 	 * @param isUseSystemClock 是否使用{@link SystemClock} 获取当前时间戳 | 	 * @param isUseSystemClock 是否使用{@link SystemClock} 获取当前时间戳 | ||||||
| 	 * @since 5.1.3 | 	 * @since 5.1.3 | ||||||
| 	 */ | 	 */ | ||||||
| 	public Snowflake(final Date epochDate, final long workerId, final long dataCenterId, final boolean isUseSystemClock) { | 	public Snowflake(final Date epochDate, final long workerId, final long dataCenterId, | ||||||
| 		this(epochDate, workerId, dataCenterId, isUseSystemClock, DEFAULT_TIME_OFFSET); | 					 final boolean isUseSystemClock) { | ||||||
| 	} | 		this(epochDate, workerId, dataCenterId, isUseSystemClock, 0); | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * @param epochDate        初始化时间起点(null表示默认起始日期),后期修改会导致id重复,如果要修改连workerId dataCenterId,慎用 |  | ||||||
| 	 * @param workerId         工作机器节点id |  | ||||||
| 	 * @param dataCenterId     数据中心id |  | ||||||
| 	 * @param isUseSystemClock 是否使用{@link SystemClock} 获取当前时间戳 |  | ||||||
| 	 * @param timeOffset       允许时间回拨的毫秒数 |  | ||||||
| 	 * @since 5.8.0 |  | ||||||
| 	 */ |  | ||||||
| 	public Snowflake(final Date epochDate, final long workerId, final long dataCenterId, final boolean isUseSystemClock, final long timeOffset) { |  | ||||||
| 		this(epochDate, workerId, dataCenterId, isUseSystemClock, timeOffset, 0); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| @@ -167,17 +146,15 @@ public class Snowflake implements Serializable { | |||||||
| 	 * @param workerId            工作机器节点id | 	 * @param workerId            工作机器节点id | ||||||
| 	 * @param dataCenterId        数据中心id | 	 * @param dataCenterId        数据中心id | ||||||
| 	 * @param isUseSystemClock    是否使用{@link SystemClock} 获取当前时间戳 | 	 * @param isUseSystemClock    是否使用{@link SystemClock} 获取当前时间戳 | ||||||
| 	 * @param timeOffset          允许时间回拨的毫秒数 |  | ||||||
| 	 * @param randomSequenceLimit 限定一个随机上限,在不同毫秒下生成序号时,给定一个随机数,避免偶数问题,0表示无随机,上限不包括值本身。 | 	 * @param randomSequenceLimit 限定一个随机上限,在不同毫秒下生成序号时,给定一个随机数,避免偶数问题,0表示无随机,上限不包括值本身。 | ||||||
| 	 * @since 5.8.0 | 	 * @since 5.8.0 | ||||||
| 	 */ | 	 */ | ||||||
| 	public Snowflake(final Date epochDate, final long workerId, final long dataCenterId, | 	public Snowflake(final Date epochDate, final long workerId, final long dataCenterId, | ||||||
| 					 final boolean isUseSystemClock, final long timeOffset, final long randomSequenceLimit) { | 					 final boolean isUseSystemClock, final long randomSequenceLimit) { | ||||||
| 		this.twepoch = (null != epochDate) ? epochDate.getTime() : DEFAULT_TWEPOCH; | 		this.twepoch = (null != epochDate) ? epochDate.getTime() : DEFAULT_TWEPOCH; | ||||||
| 		this.workerId = Assert.checkBetween(workerId, 0, MAX_WORKER_ID); | 		this.workerId = Assert.checkBetween(workerId, 0, MAX_WORKER_ID); | ||||||
| 		this.dataCenterId = Assert.checkBetween(dataCenterId, 0, MAX_DATA_CENTER_ID); | 		this.dataCenterId = Assert.checkBetween(dataCenterId, 0, MAX_DATA_CENTER_ID); | ||||||
| 		this.useSystemClock = isUseSystemClock; | 		this.useSystemClock = isUseSystemClock; | ||||||
| 		this.timeOffset = timeOffset; |  | ||||||
| 		this.randomSequenceLimit = Assert.checkBetween(randomSequenceLimit, 0, SEQUENCE_MASK); | 		this.randomSequenceLimit = Assert.checkBetween(randomSequenceLimit, 0, SEQUENCE_MASK); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -219,19 +196,16 @@ public class Snowflake implements Serializable { | |||||||
| 	public synchronized long nextId() { | 	public synchronized long nextId() { | ||||||
| 		long timestamp = genTime(); | 		long timestamp = genTime(); | ||||||
| 		if (timestamp < this.lastTimestamp) { | 		if (timestamp < this.lastTimestamp) { | ||||||
| 			if (this.lastTimestamp - timestamp < timeOffset) { | 			timestamp = lastTimestamp; | ||||||
| 				// 容忍指定的回拨,避免NTP校时造成的异常 |  | ||||||
| 				timestamp = lastTimestamp; |  | ||||||
| 			} else { |  | ||||||
| 				// 如果服务器时间有问题(时钟后退) 报错。 |  | ||||||
| 				throw new IllegalStateException(StrUtil.format("Clock moved backwards. Refusing to generate id for {}ms", lastTimestamp - timestamp)); |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (timestamp == this.lastTimestamp) { | 		if (timestamp == this.lastTimestamp) { | ||||||
|  | 			// 时间出现回拨,递增序号 | ||||||
| 			final long sequence = (this.sequence + 1) & SEQUENCE_MASK; | 			final long sequence = (this.sequence + 1) & SEQUENCE_MASK; | ||||||
| 			if (sequence == 0) { | 			if (sequence == 0) { | ||||||
| 				timestamp = tilNextMillis(lastTimestamp); | 				// 如果序号耗尽,不再等待时间追赶,而是采用“超前消费”方式,让时间递增。 | ||||||
|  | 				// 这样可以避免系统暂停等待,而选择在“未来”ID新增不快时追上来。 | ||||||
|  | 				timestamp += 1; | ||||||
| 			} | 			} | ||||||
| 			this.sequence = sequence; | 			this.sequence = sequence; | ||||||
| 		} else { | 		} else { | ||||||
| @@ -295,27 +269,6 @@ public class Snowflake implements Serializable { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// ------------------------------------------------------------------------------------------------------------------------------------ Private method start | 	// ------------------------------------------------------------------------------------------------------------------------------------ Private method start | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * 循环等待下一个时间 |  | ||||||
| 	 * |  | ||||||
| 	 * @param lastTimestamp 上次记录的时间 |  | ||||||
| 	 * @return 下一个时间 |  | ||||||
| 	 */ |  | ||||||
| 	private long tilNextMillis(final long lastTimestamp) { |  | ||||||
| 		long timestamp = genTime(); |  | ||||||
| 		// 循环直到操作系统时间戳变化 |  | ||||||
| 		while (timestamp == lastTimestamp) { |  | ||||||
| 			timestamp = genTime(); |  | ||||||
| 		} |  | ||||||
| 		if (timestamp < lastTimestamp) { |  | ||||||
| 			// 如果发现新的时间戳比上次记录的时间戳数值小,说明操作系统时间发生了倒退,报错 |  | ||||||
| 			throw new IllegalStateException( |  | ||||||
| 					StrUtil.format("Clock moved backwards. Refusing to generate id for {}ms", lastTimestamp - timestamp)); |  | ||||||
| 		} |  | ||||||
| 		return timestamp; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * 生成时间戳 | 	 * 生成时间戳 | ||||||
| 	 * | 	 * | ||||||
|   | |||||||
| @@ -94,7 +94,7 @@ public class SnowflakeTest { | |||||||
| 	@Disabled | 	@Disabled | ||||||
| 	public void snowflakeRandomSequenceTest(){ | 	public void snowflakeRandomSequenceTest(){ | ||||||
| 		final Snowflake snowflake = new Snowflake(null, 0, 0, | 		final Snowflake snowflake = new Snowflake(null, 0, 0, | ||||||
| 				false, Snowflake.DEFAULT_TIME_OFFSET, 2); | 				false, 2); | ||||||
| 		for (int i = 0; i < 1000; i++) { | 		for (int i = 0; i < 1000; i++) { | ||||||
| 			final long id = snowflake.nextId(); | 			final long id = snowflake.nextId(); | ||||||
| 			Console.log(id); | 			Console.log(id); | ||||||
| @@ -107,7 +107,7 @@ public class SnowflakeTest { | |||||||
| 	public void uniqueOfRandomSequenceTest(){ | 	public void uniqueOfRandomSequenceTest(){ | ||||||
| 		// 测试并发环境下生成ID是否重复 | 		// 测试并发环境下生成ID是否重复 | ||||||
| 		final Snowflake snowflake = new Snowflake(null, 0, 0, | 		final Snowflake snowflake = new Snowflake(null, 0, 0, | ||||||
| 				false, Snowflake.DEFAULT_TIME_OFFSET, 100); | 				false, 100); | ||||||
|  |  | ||||||
| 		final Set<Long> ids = new ConcurrentHashSet<>(); | 		final Set<Long> ids = new ConcurrentHashSet<>(); | ||||||
| 		ThreadUtil.concurrencyTest(100, () -> { | 		ThreadUtil.concurrencyTest(100, () -> { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Looly
					Looly