com.gitee.apanlh.util.id.SnowFlakeShort Maven / Gradle / Ivy
package com.gitee.apanlh.util.id;
import com.gitee.apanlh.exp.IdException;
import com.gitee.apanlh.util.thread.LockExecutor;
/**
* 雪花工具类
*
最大支持机器节点数0~31,一共32个
*
最大支持数据中心数0~31,一共32个
* @author Pan
*/
class SnowFlakeShort {
/**
* 起始的时间戳
* Tue Jul 27 01:47:45 CST 2010
* 2010-07-27 01:47:45
*/
static final long START_TIMESTAMP = 1280166465631L;
/** 序列号占用的位数 */
private static final long SEQUENCE_BIT = 12L;
/** 机器标识占用的位数 */
private static final long WORKER_BIT = 5L;
/** 数据中心占用的位数 */
private static final long DATA_CENTER_BIT = 5L;
/**
* 每一部分的最大值
* 最大支持机器节点数0~31,一共32个
* 最大支持数据中心数0~31,一共32个
*/
private static final long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);
private static final long MAX_WORKER_ID = -1L ^ (-1L << WORKER_BIT);
private static final long MAX_DATA_CENTER_ID = -1L ^ (-1L << DATA_CENTER_BIT);
/** 每一部分向左的位移 */
private static final long WORKER_LEFT = SEQUENCE_BIT;
private static final long DATA_CENTER_LEFT = SEQUENCE_BIT + WORKER_BIT;
private static final long TIMESTAMP_LEFT = DATA_CENTER_LEFT + DATA_CENTER_BIT;
/** 数据中心标识 */
private long dataCenterId;
/** 机器标识 */
private long workId;
/** 序列号 */
private long sequence = 0L;
/** 上一次时间戳 */
private long lastTimeStamp = -1L;
/**
* 构造函数
*
* @author Pan
*/
public SnowFlakeShort() {
super();
}
/**
* 根据指定的数据中心ID和机器标志ID生成指定的序列号
*
* @author Pan
* @param workId 机器标志ID
* @param dataCenterId 数据中心ID
*/
public SnowFlakeShort(long workId, long dataCenterId) {
if (workId > MAX_WORKER_ID || workId < 0L) {
throw new IllegalArgumentException("workId can't be greater than MAX_MACHINE_NUM or less than 0!");
}
if (dataCenterId > MAX_DATA_CENTER_ID || dataCenterId < 0L) {
throw new IllegalArgumentException("dataCenterId can't be greater than MAX_DATA_CENTER_NUM or less than 0!");
}
this.workId = workId;
this.dataCenterId = dataCenterId;
}
/**
* 获取下一个毫秒数
*
* @author Pan
* @return long nextMill
*/
private long getNextMill() {
long mill = getNewTimeStamp();
while (mill <= this.lastTimeStamp) {
mill = getNewTimeStamp();
}
return mill;
}
/**
* 获取当前毫秒数
*
* @author Pan
* @return long
*/
private long getNewTimeStamp() {
return System.currentTimeMillis();
}
/**
* 产生下一个ID
*
* @author Pan
* @return long
*/
private long createNextId() {
long id = LockExecutor.executeWriteLockFormReadWrite("sys_snow_flake_short_lock", () -> {
// 删除了时间回拨,如果服务器时间有问题(时钟后退) 直接报错。
long currTimeStamp = getNewTimeStamp();
if (currTimeStamp < this.lastTimeStamp) {
throw new IdException("clock moved backwards refusing to generate id");
}
if (currTimeStamp == this.lastTimeStamp) {
//相同毫秒内,序列号自增
this.sequence = (this.sequence + 1) & MAX_SEQUENCE;
//同一毫秒的序列数已经达到最大
if (this.sequence == 0L) {
currTimeStamp = getNextMill();
}
} else {
//不同毫秒内,序列号置为0
this.sequence = 0L;
}
this.lastTimeStamp = currTimeStamp;
return (currTimeStamp - START_TIMESTAMP) << TIMESTAMP_LEFT // 时间戳部分
| this.dataCenterId << DATA_CENTER_LEFT // 数据中心部分
| this.workId << WORKER_LEFT // 机器标识部分
| this.sequence; // 序列号部分
});
return id;
}
/**
* 获取雪花Id long
*
* @author Pan
* @return long
*/
public long nextId() {
return createNextId();
}
/**
* 获取雪花ID String
*
* @author Pan
* @return String
*/
public String nextIdStr() {
return Long.toString(this.nextId(), 10);
}
}