You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java生成12-13位唯一随机序列号的最佳实践

生成12-13位唯一序列号的最佳实践

首先,你当前代码的问题很明确:直接打印了Random对象本身,而不是调用它的方法生成随机数。java.util.Random@13d8cc98是对象的默认字符串表示(类名+哈希码),不是你要的序列号。

下面分场景给出解决方案:

基础场景:低并发、对唯一性要求一般

如果只是简单生成12-13位随机数,且不会在同一毫秒内频繁生成,可按以下方式修正代码:

// 用当前毫秒时间做种子初始化Random
Random random = new Random(System.currentTimeMillis());
// 定义12-13位的范围:100000000000(12位最小值)到9999999999999(13位最大值)
long min = 100000000000L;
long max = 9999999999999L;
long range = max - min + 1;

// 生成指定范围的随机数(处理nextLong()可能返回负数的情况)
long serialNo = min + (random.nextLong() & Long.MAX_VALUE) % range;

System.out.println("serial number is " + serialNo);

关键优化点:

  • 不要每次生成序列号都新建Random实例,复用同一个实例能避免同一毫秒内种子重复导致的随机序列重复:
    // 全局复用一个Random实例
    private static final Random RANDOM = new Random(System.currentTimeMillis());
    
    public static long getSerialNo() {
        long min = 100000000000L;
        long max = 9999999999999L;
        long range = max - min + 1;
        return min + (RANDOM.nextLong() & Long.MAX_VALUE) % range;
    }
    

进阶场景:需要较高唯一性

如果要进一步降低重复概率,建议结合时间戳+随机数的方式,利用时间的递增性减少冲突:

public static String generateSerialNo() {
    // 取当前毫秒时间戳的后10位(保证时间维度的唯一性基础)
    String timeSegment = String.valueOf(System.currentTimeMillis()).substring(3);
    // 生成2-3位随机数(让总长度在12-13位之间)
    Random random = new Random();
    int randomSegment = random.nextInt(900) + 100; // 生成3位随机数;若要2位则用random.nextInt(90)+10
    
    return timeSegment + randomSegment;
}

这种方式生成的序列号既包含时间信息,又有随机部分,短时间内重复的概率极低。

高级场景:分布式/高并发下严格唯一

如果是分布式系统或高并发场景,要求序列号绝对唯一,可使用简化版雪花算法,通过拆分时间戳、机器标识、序列号的方式保证唯一性:

public class SerialGenerator {
    // 起始时间戳(自定义,比如2024-01-01 00:00:00)
    private static final long START_TIMESTAMP = 1704067200000L;
    private static long lastTimestamp = -1L;
    private static int sequence = 0;
    // 同一毫秒内最多生成10个不同序列号
    private static final int MAX_SEQUENCE = 9;

    // 加锁保证线程安全
    public static synchronized String generate() {
        long currentTimestamp = System.currentTimeMillis();
        
        // 处理时钟回退问题
        if (currentTimestamp < lastTimestamp) {
            throw new RuntimeException("Clock moved backwards. Cannot generate serial number.");
        }

        // 同一毫秒内递增序列号
        if (currentTimestamp == lastTimestamp) {
            sequence = (sequence + 1) % (MAX_SEQUENCE + 1);
            if (sequence == 0) {
                // 等待下一个毫秒
                while (currentTimestamp <= lastTimestamp) {
                    currentTimestamp = System.currentTimeMillis();
                }
            }
        } else {
            sequence = 0;
        }

        lastTimestamp = currentTimestamp;
        
        // 时间差部分(取10位,保证约3年的可用周期)
        long timeDiff = currentTimestamp - START_TIMESTAMP;
        String timeStr = String.format("%010d", timeDiff);
        // 机器标识(自定义,比如机器IP后两位、进程ID,这里简化为固定值)
        String machineId = "01";
        // 序列号部分(1位)
        String sequenceStr = String.valueOf(sequence);

        // 组合成13位序列号:10位时间差 + 2位机器标识 + 1位序列号
        return timeStr + machineId + sequenceStr;
    }
}

说明:

  • 时间差部分:基于起始时间的差值,避免时间戳过长
  • 机器标识:区分不同节点,防止分布式场景下的重复
  • 序列号:同一毫秒内同一节点生成的序列号递增,保证毫秒内唯一

内容的提问来源于stack exchange,提问作者Anshul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 19:40:18