第三方工具

   		<dependency>
            <groupId>cn.hutool</groupId>
            &lt;artifactId&gt;hutool-all</artifactId>
            <version>5.8.6</version>
        </dependency>

代码示例

   @Test
    public void test(){
        System.out.println(IdUtil.getSnowflakeNextId());
    }

API

package cn.hutool.core.util;

import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.ObjectId;
import cn.hutool.core.lang.Singleton;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.lang.id.NanoId;
import cn.hutool.core.net.NetUtil;

public class IdUtil {
    public IdUtil() {
    }

    public static String randomUUID() {
        return UUID.randomUUID().toString();
    }

    public static String simpleUUID() {
        return UUID.randomUUID().toString(true);
    }

    public static String fastUUID() {
        return UUID.fastUUID().toString();
    }

    public static String fastSimpleUUID() {
        return UUID.fastUUID().toString(true);
    }

    public static String objectId() {
        return ObjectId.next();
    }

    /** @deprecated */
    @Deprecated
    public static Snowflake createSnowflake(long workerId, long datacenterId) {
        return new Snowflake(workerId, datacenterId);
    }

    public static Snowflake getSnowflake(long workerId, long datacenterId) {
        return (Snowflake)Singleton.get(Snowflake.class, new Object[]{workerId, datacenterId});
    }

    public static Snowflake getSnowflake(long workerId) {
        return (Snowflake)Singleton.get(Snowflake.class, new Object[]{workerId});
    }

    public static Snowflake getSnowflake() {
        return (Snowflake)Singleton.get(Snowflake.class, new Object[0]);
    }

    public static long getDataCenterId(long maxDatacenterId) {
        Assert.isTrue(maxDatacenterId > 0L, "maxDatacenterId must be > 0", new Object[0]);
        if (maxDatacenterId == Long.MAX_VALUE) {
            --maxDatacenterId;
        }

        long id = 1L;
        byte[] mac = null;

        try {
            mac = NetUtil.getLocalHardwareAddress();
        } catch (UtilException var6) {
        }

        if (null != mac) {
            id = (255L &amp; (long)mac[mac.length - 2] | 65280L &amp; (long)mac[mac.length - 1] << 8) >> 6;
            id %= maxDatacenterId + 1L;
        }

        return id;
    }

    public static long getWorkerId(long datacenterId, long maxWorkerId) {
        StringBuilder mpid = new StringBuilder();
        mpid.append(datacenterId);

        try {
            mpid.append(RuntimeUtil.getPid());
        } catch (UtilException var6) {
        }

        return (long)(mpid.toString().hashCode() &amp; 'uffff') % (maxWorkerId + 1L);
    }

    public static String nanoId() {
        return NanoId.randomNanoId();
    }

    public static String nanoId(int size) {
        return NanoId.randomNanoId(size);
    }

    public static long getSnowflakeNextId() {
        return getSnowflake().nextId();
    }

    public static String getSnowflakeNextIdStr() {
        return getSnowflake().nextIdStr();
    }
}

生成18位雪花Id

public class SnowFlake {
    // 起始的时间戳,这个时间可以是你的系统初始时间,一般取当前时间
    private final static long START_TIMESTAMP = 1672502400000L; // 2023-01-01 00:00:00

    // 每一部分占用位数可以根据自己需求进行调整,这里是按照默认的占位数进行分配
    private final static long SEQUENCE_BIT = 12; // 序列号占用位数
    private final static long MACHINE_BIT = 5; // 机器标识占用位数
    private final static long DATA_CENTER_BIT = 5; // 数据中心占用位数

    // 每一部分最大值可以根据占用位数进行计算得到
    private final static long MAX_SEQUENCE = ~(-1L << SEQUENCE_BIT);
    private final static long MAX_MACHINE_NUM = ~(-1L << MACHINE_BIT);
    private final static long MAX_DATA_CENTER_NUM = ~(-1L << DATA_CENTER_BIT);

    // 每一部分向左的位移计算出来的值是为了后面生成 ID 做准备
    private final static long MACHINE_LEFT = SEQUENCE_BIT;
    private final static long DATA_CENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
    private final static long TIMESTAMP_LEFT = DATA_CENTER_LEFT + DATA_CENTER_BIT;

    private long dataCenterId; // 数据中心 ID
    private long machineId; // 机器 ID
    private long sequence = 0L; // 序列号
    private long lastTimeStamp = -1L; // 上一次时间

    /**
     * <h2>构造方法</h2>
     *
     * @param dataCenterId 数据中心 ID
     * @param machineId    机器 ID
     */
    public SnowFlake(long dataCenterId, long machineId) {
        if (dataCenterId > MAX_DATA_CENTER_NUM || dataCenterId < 0) {
            throw new IllegalArgumentException("数据中心标识不能大于等于 " + MAX_DATA_CENTER_NUM + " 或小于 0");
        }
        if (machineId > MAX_MACHINE_NUM || machineId < 0) {
            throw new IllegalArgumentException("机器标识不能大于等于 " + MAX_MACHINE_NUM + " 或小于 0");
        }
        this.dataCenterId = dataCenterId;
        this.machineId = machineId;
    }

    /**
     * <h2>雪花算法核心方法</h2>
     * 通过调用 nextId() 方法,让当前这台机器上的 snowflake 算法程序生成一个全局唯一id
     */
    public synchronized long nextId() {
        // 获取系统当前时间
        long currentTimeStamp = getSystemCurrentTimeMillis();
        if (currentTimeStamp < lastTimeStamp) {
            throw new RuntimeException("时钟向后移动拒绝生成雪花算法ID");
        }

        if (currentTimeStamp == lastTimeStamp) {
            // 当前毫秒内,序列号自增
            sequence = (sequence + 1) & MAX_SEQUENCE;
            // 序列号超出范围需要等待下一毫秒
            if (sequence == 0L) {
                // 获取下一毫秒
                currentTimeStamp = getNextMill(lastTimeStamp);
            }
        } else {
            // 不同毫秒内,序列号置为 0
            sequence = 0L;
        }

        lastTimeStamp = currentTimeStamp;

        // 使用运算生成最终的 ID
        return (currentTimeStamp - START_TIMESTAMP) << TIMESTAMP_LEFT
                | dataCenterId << DATA_CENTER_LEFT
                | machineId << MACHINE_LEFT
                | sequence;
    }

    /**
     * <h2>获取系统当前时间戳</h2>
     *
     * @return 当前时间(毫秒)
     */
    private long getSystemCurrentTimeMillis() {
        return System.currentTimeMillis();
    }

    /**
     * <h2>获取下一毫秒</h2>
     * 当某一毫秒的时间,产生的 id 数 超过4095,系统会进入等待,直到下一毫秒,系统继续产生 ID
     *
     * @param lastTimestamp 上次生成 ID 的时间截
     * @return 当前时间戳
     */
    private long getNextMill(long lastTimestamp) {
        long timeMillis = getSystemCurrentTimeMillis();
        while (timeMillis <= lastTimestamp) {
            timeMillis = getSystemCurrentTimeMillis();
        }
        return timeMillis;
    }

    public static void main(String[] args) {
        SnowFlake worker1 = new SnowFlake(1, 1);
        System.out.println(worker1.nextId());
    }
}

生成13位雪花Id

package com.ais.common.web.utils;

public class IdUtil {
    /**
     * 开始时间截 (本次时间戳为:Thu Nov 04 2010 09:42:54 GMT+0800 (中国标准时间)----1288834974657L---1656543015264587776--19 )
     */
    private final long startTime = 1683803335498L;

    /**
     * 机器id所占的位数
     */
    private final long workerIdBits = 3L;

    /**
     * 支持最大机器id结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示最大进制数)
     */
    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);

    /**
     * 序列在id中占的位数
     */
    private final long sequenceBits = 5L;

    /**
     * 机器ID向左移12位
     */
    private final long workerIdShift = sequenceBits;

    /**
     * 时间截向左移22位(10+12)
     */
    private final long timestampLeftShift = sequenceBits + workerIdBits;

    /**
     * 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095)
     */
    private final long sequenceMask = -1L ^ (-1L << sequenceBits);

    /**
     * 工作机器ID(0~1024)
     */
    private long workerId;

    /**
     * 毫秒内序列(0~4095)
     */
    private long sequence = 0L;

    /**
     * 上次生成ID的时间截
     */
    private long lastTimestamp = -1L;
    private final static IdUtil idWorker = new IdUtil(1);
    //==============================Constructors=====================================

    /**
     * 构造函数
     *
     * @param workerId 工作ID (0~1024)
     */
    public IdUtil(long workerId) {
        if (workerId > maxWorkerId || workerId < 0) {
            throw new IllegalArgumentException(String.format("workerId can't be greater than %d or less than 0", maxWorkerId));
        }
        this.workerId = workerId;
    }

    // ==============================Methods==========================================

    /**
     * 获得下一个ID (该方法线程安全的)
     *
     * @return SnowflakeId
     */
    public synchronized long nextId() {
        long timestamp = timeGen();

        //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
        if (timestamp < lastTimestamp) {
            throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
        }

        //如果是同一时间生成的,则进行毫秒内序列
        if (lastTimestamp == timestamp) {
            sequence = (sequence + 1) & sequenceMask;
            //毫秒内序列溢出
            if (sequence == 0) {
                //阻塞到下一个毫秒,获得新的时间戳
                timestamp = tilNextMillis(lastTimestamp);
            }
        }
        //时间戳改变,毫秒内序列重置
        else {
            sequence = 0L;
        }

        //上次生成ID的时间截
        lastTimestamp = timestamp;

        //移位并通过运算拼到一起组成64位的ID
        return ((timestamp - startTime) << timestampLeftShift) | (workerId << workerIdShift) | sequence;
    }

    /**
     * 阻塞到下一个毫秒,直到获得新的时间戳
     *
     * @param lastTimestamp 上次生成ID的时间截
     * @return 当前时间戳
     */
    protected long tilNextMillis(long lastTimestamp) {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }

    /**
     * 返回以毫秒为单位的当前时间
     *
     * @return 当前时间(毫秒)
     */
    protected long timeGen() {
        return System.currentTimeMillis();
    }

    public static long getSnowflakeNextId() {
        return idWorker.nextId();
    }

    /**
     * 测试
     */
    public static void main(String[] args) {
        System.out.println(IdUtil.getSnowflakeNextId());
    }
}

原文地址:https://blog.csdn.net/qq_42702751/article/details/134730046

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_24096.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注