类名
SnowflakeIdUtils —— 全局唯一ID生成工具类
功能概览
-
长整型雪花ID
-
方法:
nextId() -
返回类型:
long -
特点:基于 Twitter 的 Snowflake 算法生成 64 位全局唯一ID
-
组成结构:
1bit 符号位 + 41bit 时间戳 + 10bit 机器ID + 12bit 序列号 -
适用场景:数据库主键、分布式唯一标识
-
-
数字字符串形式的雪花ID
- 方法:
nextIdStr() - 返回类型:
String - 特点:将 long 类型雪花ID 转为字符串,方便前端展示或传输
- 适用场景:接口返回 ID、JSON 数据字段
- 方法:
-
带日期前缀的雪花ID
- 方法:
nextIdWithDate() - 返回类型:
String - 格式:
YYYYMMDD_雪花ID - 特点:增加日期前缀,便于按日期分组或归档
- 适用场景:日志编号、报表编号、每日流水号
- 方法:
-
自定义前缀 + 日期 + 雪花ID
- 方法:
nextIdWithPrefix(String prefix) - 返回类型:
String - 格式:
前缀_YYYYMMDD_雪花ID - 特点:可添加业务前缀(如 "QR"、"FILE"、"ORD"),兼顾业务标识和唯一性
- 适用场景:文件名、订单号、二维码编号
- 方法:
-
秒级时间戳 + 随机后缀ID
- 方法:
nextIdWithRandom() - 返回类型:
String - 格式:
yyyyMMddHHmmss + 4位随机数 - 特点:适合对唯一性要求较低但要求短ID、可读性强的场景
- 适用场景:文件名、二维码、短期唯一标识
- 方法:
核心设计特点
-
线程安全
- 使用
synchronized确保雪花ID生成器在高并发环境下不会重复生成ID
- 使用
-
支持自定义机器ID
- 方法:
setMachineId(long id) - 范围:0~1023
- 适用于多节点分布式环境,保证不同机器生成的ID不会冲突
- 方法:
-
雪花算法特性
- 高性能:可在毫秒级别生成多条唯一ID
- 分布式友好:机器ID + 时间戳 + 序列号
- 可排序:生成的ID按时间递增
-
易用性
- 提供多种生成方法满足不同业务需求
- 返回值类型灵活(
long/String) - 可带日期或自定义前缀,便于业务追踪和管理
使用示例
package com.aj.parkofficesystem.utils;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ThreadLocalRandom;
/**
* 全局雪花ID工具类 + 秒级时间戳 + 随机后缀ID
*
* 功能:
* 1. long 类型雪花ID
* 2. 数字字符串雪花ID
* 3. 带日期前缀的雪花ID(YYYYMMDD_数字ID)
* 4. 自定义前缀 + 日期 + 雪花ID
* 5. 秒级时间戳 + 随机后缀ID(适合文件名、二维码等)
*
* 使用方式:
* SnowflakeIdUtils.nextId(); // long 类型
* SnowflakeIdUtils.nextIdStr(); // 数字字符串
* SnowflakeIdUtils.nextIdWithDate(); // 日期前缀
* SnowflakeIdUtils.nextIdWithPrefix("QR"); // 自定义前缀
* SnowflakeIdUtils.nextIdWithRandom(); // 秒级时间戳 + 随机后缀
*/
public class SnowflakeIdUtils {
// ============================== 基础配置 ==============================
/** 起始时间戳(自定义纪元)2023-01-01 00:00:00 */
private static final long START_STAMP = 1672531200000L;
/** 序列号占用位数(12位) */
private static final long SEQUENCE_BIT = 12;
/** 机器ID占用位数(10位) */
private static final long MACHINE_BIT = 10;
/** 最大机器ID值(0~1023) */
private static final long MAX_MACHINE_NUM = ~(-1L << MACHINE_BIT);
/** 最大序列号值(0~4095) */
private static final long MAX_SEQUENCE = ~(-1L << SEQUENCE_BIT);
/** 机器ID左移偏移量 */
private static final long MACHINE_LEFT = SEQUENCE_BIT;
/** 时间戳左移偏移量 */
private static final long TIMESTAMP_LEFT = SEQUENCE_BIT + MACHINE_BIT;
/** 默认机器ID(可根据服务实例设置) */
private static final long DEFAULT_MACHINE_ID = 1L;
// ============================== 运行状态 ==============================
/** 当前机器ID */
private static long machineId = DEFAULT_MACHINE_ID;
/** 当前毫秒内序列号 */
private static long sequence = 0L;
/** 上一次生成ID的时间戳 */
private static long lastStamp = -1L;
/** 禁止实例化 */
private SnowflakeIdUtils() {}
// ============================== 核心方法 ==============================
/**
* 设置机器ID(0~1023)
* @param id 机器ID
*/
public static void setMachineId(long id) {
if (id < 0 || id > MAX_MACHINE_NUM) {
throw new IllegalArgumentException("机器ID超出范围(0~1023)");
}
machineId = id;
}
/**
* 获取下一个全局唯一ID(long 类型)
* @return long 类型ID
*/
public synchronized static long nextId() {
long currStamp = System.currentTimeMillis();
// 时钟回拨检测
if (currStamp < lastStamp) {
throw new RuntimeException("时钟回拨,拒绝生成ID");
}
// 同一毫秒内生成多个ID
if (currStamp == lastStamp) {
sequence = (sequence + 1) & MAX_SEQUENCE;
// 当前毫秒序列用完,等待下一毫秒
if (sequence == 0L) {
currStamp = waitNextMillis(currStamp);
}
} else {
// 新的毫秒,序列号从0开始
sequence = 0L;
}
lastStamp = currStamp;
// 组合ID:时间戳部分 + 机器ID部分 + 序列号部分
return (currStamp - START_STAMP) << TIMESTAMP_LEFT
| (machineId << MACHINE_LEFT)
| sequence;
}
/**
* 获取下一个全局唯一ID(数字字符串形式)
* @return String 类型ID
*/
public static String nextIdStr() {
return String.valueOf(nextId());
}
/**
* 获取带日期前缀的全局唯一ID(YYYYMMDD_数字ID)
* @return 日期前缀ID
*/
public static String nextIdWithDate() {
String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
return date + "_" + nextId();
}
/**
* 获取自定义前缀 + 日期 + 数字ID
* 例如:QR_20251027_4523367890123456789
* @param prefix 自定义前缀(如 "QR", "FILE", "ORD")
* @return 带前缀ID
*/
public static String nextIdWithPrefix(String prefix) {
String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
return prefix + "_" + date + "_" + nextId();
}
/**
* 获取秒级时间戳 + 随机后缀ID
* 格式:yyyyMMddHHmmss + 4位随机数
* 适合文件名、二维码等
* @return 秒级时间戳 + 随机后缀ID
*/
public static String nextIdWithRandom() {
// 当前时间,精确到秒
String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
// 随机数(1000~9999)
int random = ThreadLocalRandom.current().nextInt(1000, 10000);
return timestamp + random;
}
/**
* 等待下一毫秒
* @param currStamp 当前时间戳
* @return 下一毫秒时间戳
*/
private static long waitNextMillis(long currStamp) {
while (currStamp <= lastStamp) {
currStamp = System.currentTimeMillis();
}
return currStamp;
}
}
public class Demo {
public static void main(String[] args) {
// 设置机器ID(可选)
SnowflakeIdUtils.setMachineId(2);
// long 类型雪花ID
long id1 = SnowflakeIdUtils.nextId();
// 数字字符串形式
String id2 = SnowflakeIdUtils.nextIdStr();
// 日期前缀ID
String id3 = SnowflakeIdUtils.nextIdWithDate();
// 自定义前缀ID
String id4 = SnowflakeIdUtils.nextIdWithPrefix("QR");
// 秒级时间戳 + 随机数ID
String id5 = SnowflakeIdUtils.nextIdWithRandom();
System.out.println(id1);
System.out.println(id2);
System.out.println(id3);
System.out.println(id4);
System.out.println(id5);
}
}
总结
SnowflakeIdUtils 是一个 全能型 ID 工具类,将雪花ID和秒级随机ID统一封装。 提供多种生成方式,覆盖数据库主键、文件名、二维码、报表编号等常见业务场景。 线程安全、分布式可用、易于扩展。 可轻松在项目中直接调用,不需要额外依赖。