Java实现雪花算法(snowflake)

Java实现雪花算法(snowflake)

雪花算法是一种可以生成全局唯一ID的算法,它可以用于分布式系统中的ID生成。下面是Java实现雪花算法(snowflake)的完整攻略,包含过程中至少两条示例说明。

算法思路

雪花算法可以生成64位的唯一ID,其生成规则如下:

  • 1位标识符:符号位,在雪花算法中始终为0,表示正数。
  • 41位时间戳:记录生成ID的时间,表示从"起始时间"开始经过的毫秒数。41位可以支持69年的时间戳。
  • 10位机器标识:可以部署在1024台机器上,要求在同一毫秒内产生的ID是不同的。
  • 12位序列号:在同一毫秒内,可以产生4096个不同的序列号。

Java实现

Java实现雪花算法,可以使用如下代码:

public class SnowflakeIdGenerator {
    private static final long twepoch = System.currentTimeMillis();

    private static final long workerIdBits = 10L;
    private static final long maxWorkerId = -1L ^ (-1L << workerIdBits);
    private static final long sequenceBits = 12L;

    private static final long workerIdShift = sequenceBits;
    private static final long timestampLeftShift = sequenceBits + workerIdBits;
    private static final long sequenceMask = -1L ^ (-1L << sequenceBits);

    private long workerId;
    private long sequence = 0L;
    private long lastTimestamp = -1L;

    public SnowflakeIdGenerator(long workerId) {
        if (workerId > maxWorkerId || workerId < 0L) {
            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
        }
        this.workerId = workerId;
    }

    public synchronized long nextId() {
        long timestamp = timeGen();

        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;
        }

        lastTimestamp = timestamp;

        return ((timestamp - twepoch) << timestampLeftShift) |
                (workerId << workerIdShift) |
                sequence;
    }

    private long tilNextMillis(long lastTimestamp) {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }

    private long timeGen() {
        return System.currentTimeMillis();
    }
}

在上述代码中:

  • twepoch是一个起始时间,用于计算时间戳。
  • workerIdBits是机器标识的位数,为10位,在示例中使用了一个long类型的变量。
  • maxWorkerId是机器标识的最大值,根据机器标识位数计算出来。
  • sequenceBits是序列号的位数,为12位,在示例中使用了一个long类型的变量。
  • workerIdShift是机器标识的左移位数,根据序列号位数计算出来。
  • timestampLeftShift是时间戳的左移位数,根据序列号和机器标识位数计算出来。
  • sequenceMask是序列号的掩码,根据序列号位数计算出来。

在SnowflakeIdGenerator类中,nextId()方法用于生成ID,tilNextMillis()方法用于等待下一毫秒。同时,都使用了synchronized让这些方法保证线程安全。

示例说明

下面是两个示例说明:

示例一

在这个示例中,我们使用一台机器,使用了两个SnowflakeIdGenerator生成10个ID,代码如下:

public class Example1 {
    public static void main(String[] args) {
        SnowflakeIdGenerator generator1 = new SnowflakeIdGenerator(1L);
        SnowflakeIdGenerator generator2 = new SnowflakeIdGenerator(2L);

        for (int i = 0; i < 5; i++) {
            System.out.println(generator1.nextId());
        }

        for (int i = 0; i < 5; i++) {
            System.out.println(generator2.nextId());
        }
    }
}

输出结果:

680131594107310848
680131594107310849
680131594107310850
680131594107310851
680131594107310852
687596776048314881
687596776048314882
687596776048314883
687596776048314884
687596776048314885

示例二

在这个示例中,我们使用三台机器,分别使用了三个SnowflakeIdGenerator生成10个ID,代码如下:

public class Example2 {
    public static void main(String[] args) {
        SnowflakeIdGenerator generator1 = new SnowflakeIdGenerator(1L);
        SnowflakeIdGenerator generator2 = new SnowflakeIdGenerator(2L);
        SnowflakeIdGenerator generator3 = new SnowflakeIdGenerator(3L);

        for (int i = 0; i < 5; i++) {
            System.out.println(generator1.nextId());
        }

        for (int i = 0; i < 5; i++) {
            System.out.println(generator2.nextId());
        }

        for (int i = 0; i < 5; i++) {
            System.out.println(generator3.nextId());
        }
    }
}

输出结果:

854590986602096640
854590986602096641
854590986602096642
854590986602096643
854590986602096644
854590986602096645
854590986602096646
854590986602096647
854590986602096648
854590986602096649
758515964259520513
758515964259520514
758515964259520515
758515964259520516
758515964259520517
973074594719193345
973074594719193346
973074594719193347
973074594719193348
973074594719193349

可以看到,在示例二中,三台机器都可以生成唯一的ID,并且在同一毫秒内产生的ID是不同的。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java实现雪花算法(snowflake) - Python技术站

(0)
上一篇 2023年5月18日
下一篇 2023年5月18日

相关文章

  • JVM入门之内存结构(堆、方法区)

    JVM入门之内存结构(堆、方法区) JVM是Java虚拟机的缩写,是Java技术的核心和基础。学习JVM内存结构对于Java程序员来说非常重要,本文将对JVM内存结构、堆和方法区进行详细讲解。 JVM内存结构 JVM的内存结构主要由以下几个部分组成: 程序计数器 虚拟机栈 本地方法栈 堆 方法区 其中堆和方法区是Java程序中数据存储的主要区域,我们重点来详…

    Java 2023年5月26日
    00
  • 用intellij Idea加载eclipse的maven项目全流程(图文)

    以下是详细讲解“用IntelliJ Idea加载Eclipse的Maven项目全流程”的完整攻略。 步骤1:安装IntelliJ Idea 首先,需要在本地安装IntelliJ Idea,如果还没有安装,请官网下载并安装。 步骤2:打开IntelliJ Idea 安装完成后,打开IntelliJ Idea,点击菜单中的“Import Project” 步骤3…

    Java 2023年5月20日
    00
  • IDEA项目使用SpringBoot+MyBatis-Plus的方法

    这里是详细的讲解“IDEA项目使用SpringBoot+MyBatis-Plus的方法”的完整攻略,包含了两条示例。 准备条件 为了完成本攻略,你需要事先准备以下条件: JDK 8及以上版本 IntelliJ IDEA 2020.3或以上版本 Maven 3.0及以上版本 SpringBoot 2.4.x版本 MyBatis-Plus 3.x版本 数据库(本…

    Java 2023年5月20日
    00
  • 简单了解Java关键字throw和throws的区别

    简单了解Java关键字throw和throws的区别 在Java中,throw和throws是两个与异常相关的关键字,它们的作用和使用场景不同,但经常容易混淆。 throw关键字 throw关键字用于抛出一个异常对象。我们可以在代码中手动抛出一个异常对象并且将其名称直接传递给throw语句。抛出异常后,程序会立即终止当前的语句执行,并开始执行异常处理流程。 …

    Java 2023年5月25日
    00
  • 微信小程序 免费SSL证书https、TLS版本问题的解决办法

    针对“微信小程序 免费SSL证书https、TLS版本问题的解决办法”,我提供如下完整攻略。 什么是SSL证书和TLS版本 SSL证书可以理解为电子商务网站的身份证,用于证明网站的身份,并通过加密通讯来保护信息不被窃取。而TLS是SSL的升级版本,用于加密网络连接,并确保数据的完整性和机密性。 微信小程序使用SSL证书和TLS版本的必要性 微信小程序要求所有…

    Java 2023年5月23日
    00
  • 深入浅出理解Java Lambda表达式之四大核心函数式的用法与范例

    来看看如何深入浅出地理解Java Lambda表达式之四大核心函数式的用法与范例。 一、什么是Lambda表达式? Lambda表达式是Java 8中引入的一个重大语言特性,可以看作一种匿名函数,使Java在函数式编程方面有了重大的改进。跟匿名类不同,Lambda表达式不需要声明类型,编译器可以自动推断Lambda表达式的类型。 Lambda表达式简化了Ja…

    Java 2023年5月26日
    00
  • idea使用jclasslib插件查看字节码

    下面是使用jclasslib插件查看字节码的完整攻略。 简介 jclasslib是一款Java字节码编辑器,可以用于查看、分析Java类文件的字节码。除了常规的字节码指令和常量池信息外,它还能够查看方法、字段、注解、接口等相关信息。 同时,jclasslib还提供Intellij IDEA插件,让开发者能够直接在IDEA中使用jclasslib功能,进行更为…

    Java 2023年5月26日
    00
  • SpringBoot实战教程之新手入门篇

    SpringBoot实战教程之新手入门篇攻略 SpringBoot是一种快速开发、简化配置的Java框架。它集成了常用的开发工具,如SpringMVC、Hibernate、MyBatis等,能够帮助开发人员快速搭建Java Web项目。本篇攻略将介绍学习SpringBoot的入门教程。 1. 安装Java和IDE 在开始学习SpringBoot之前,需要先安…

    Java 2023年5月15日
    00
合作推广
合作推广
分享本页
返回顶部