SnowFlake所生成的ID一共分成四部分:

1.第一位
占用1bit,其值始终是0,没有实际作用。

2.时间戳
占用41bit,精确到毫秒,总共可以容纳约69 年的时间。

3.工作机器id
占用10bit,其中高位5bit是数据中心ID(datacenterId),低位5bit是工作节点ID(workerId),做多可以容纳1024个节点。

4.序列号
占用12bit,这个值在同一毫秒同一节点上从0开始不断累加,最多可以累加到4095。

SnowFlake算法在同一毫秒内最多可以生成多少个全局唯一ID呢?只需要做一个简单的乘法:

同一毫秒的ID数量 = 1024 X 4096 = 4194304

这个数字在绝大多数并发场景下都是够用的。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; /**
* Created by xfyou 2018/6/8 14:01.
*/
public class SnowFlakeIdGenerator {
// The initial time(2017-01-01)
private static final long INITIAL_TIME_STAMP = 1483200000000L; // Machine ID bits
private static final long WORK_ID_BITS = 5L; // DataCenter ID bits
private static final long DATACENTER_ID_BITS = 5L; // The maximum machine ID supported is 31, which can quickly calculate the maximum decimal number that a few binary numbers can represent.
private static final long MAX_WORKER_ID = ~(-1L << WORK_ID_BITS); // The maximum datacenter ID supported is 31
private static final long MAX_DATACENTER_ID = ~(-1L << DATACENTER_ID_BITS); // Sequence ID bits
private static final long SEQUENCE_BITS = 12L; // The machine ID offset,12
private static final long WORKERID_OFFSET = SEQUENCE_BITS; // The datacent ID offset,12+5
private static final long DATACENTERID_OFFSET = WORK_ID_BITS + SEQUENCE_BITS; // The timestape offset, 5+5+12
private static final long TIMESTAMP_OFFSET = DATACENTER_ID_BITS + WORK_ID_BITS + SEQUENCE_BITS; // Sequence mask,4095
private static final long SEQUENCE_MASK = ~(-1L << SEQUENCE_BITS); // Worker ID ,0~31
private long workerId; // Datacenter ID,0~31
private long datacenterId; // Sequence,0~4095
private long sequence = 0L; // Last timestamp
private long lastTimestamp = -1L; public SnowFlakeIdGenerator(long workerId, long datacenterId) {
if (workerId > MAX_WORKER_ID || workerId < 0)
throw new IllegalArgumentException(String.format("WorkerID can't be greater than %d or less than 0", MAX_WORKER_ID));
if (datacenterId > MAX_DATACENTER_ID || datacenterId < 0)
throw new IllegalArgumentException(String.format("DataCenterID can't be greater than %d or less than 0", MAX_WORKER_ID));
this.workerId = workerId;
this.datacenterId = datacenterId;
} public synchronized long nextId() {
long timeStamp = System.currentTimeMillis();
if (timeStamp < lastTimestamp)
throw new RuntimeException("The current time less than last time");
if (timeStamp == lastTimestamp) {
sequence = (sequence + 1) & SEQUENCE_MASK;
if (0 == sequence)
timeStamp = tillNextMillis(lastTimestamp);
} else {
sequence = 0L;
}
lastTimestamp = timeStamp; return (timeStamp - INITIAL_TIME_STAMP) << TIMESTAMP_OFFSET | (datacenterId << DATACENTERID_OFFSET) | (workerId << WORKERID_OFFSET) | sequence;
} private long tillNextMillis(long lastTimestamp) {
long timestamp = System.currentTimeMillis();
while (timestamp <= lastTimestamp)
timestamp = System.currentTimeMillis();
return timestamp;
} public static void main(String[] args) {
SnowFlakeIdGenerator generator = new SnowFlakeIdGenerator(1, 1);
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
long id = generator.nextId();
System.out.println(id);
}
});
}
executorService.shutdown();
}
}

一个可能的输出为:

189783462515970048
189783462515970049
189783462515970050
189783462515970051
189783462520164352

Java 实现的SnowFlake生成UUID (Java代码实战-007)的更多相关文章

  1. [转]java二维码生成与解析代码实现

    转载地址:点击打开链接 二维码,是一种采用黑白相间的平面几何图形通过相应的编码算法来记录文字.图片.网址等信息的条码图片.如下图 二维码的特点: 1.  高密度编码,信息容量大 可容纳多达1850个大 ...

  2. java二维码生成与解析代码实现

    TwoDimensionCode类:二维码操作核心类 package qrcode; import java.awt.Color; import java.awt.Graphics2D; import ...

  3. Java编程思想-注解生成外部例子代码

    如果本文帮助到您,请点击下面的链接,这是本人的网站,以示鼓励,谢谢!链接绝对安全! 本人的网站 java注解属于java中高大上的功能,许多开源框架都使用了java注解的功能.比如spring,hib ...

  4. 生成UUID的代码

    代码: String reqId = UUID.randomUUID().toString().replace("-", "");

  5. java生成UUID

    UUID介绍: UUID(Universally Unique Identifier)全局唯一标识符,是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的.按照开放软件基金会(OSF) ...

  6. JAVA基础知识(一)—JAVA概述

    JAVA概述 1991 年Sun公司的James Gosling(詹姆斯·高斯林)等人开始开发名称为 Oak 的语言,希望用于控制嵌入在有线电视交换盒.PDA等的微处理器: 1994年将Oak语言更名 ...

  7. 利用Java生成UUID

    UUID是什么? UUID 是 通用唯一识别码(Universally Unique Identifier)的缩写,是一种软件建构的标准,亦为开放软件基金会组织在分布式计算环境领域的一部分.其目的,是 ...

  8. java 生成UUID

    UUID(Universally Unique Identifier)全局唯一标识符,是一个128位长的数字,一般用16进制表示. 算法的核心思想是结合机器的网卡.当地时间.一个随即数来生成UUID, ...

  9. java生成UUID通用唯一识别码 (Universally Unique Identifier)

    转自:http://blog.csdn.net/carefree31441/article/details/3998553 UUID含义是通用唯一识别码 (Universally Unique Ide ...

随机推荐

  1. Petri网

    Petri网是一种适合于系统描述和分析的数学模型,主要描述异步和并发关系.(或者Petri网是对离散并行系统的数学表示,适用于描述异步的,并发的计算机系统模型.) Petri网模型自然,直观,简单易懂 ...

  2. [转]Sphinx+Mysql+中文分词安装-实现中文全文搜索

    From : http://blog.csdn.net/lgm252008/article/details/5373436 1.什么是SphinxSphinx 是一个在GPLv2 下发布的一个全文检索 ...

  3. HTTPS安全证书介绍

    IIS配置web SSL 安全证书Https访问 From : http://cao416451347ming.blog.163.com/blog/static/1154556162010217441 ...

  4. Maven中的库(repository)详解

    Maven中的库(repository)是构件(artifact)的集合.构件以一定的布局存储在库中. 本地仓库 vs. 远程仓库 运行Maven的时候,Maven所需要的任何构件都是直接从本地仓库获 ...

  5. .net 系列:Expression表达式树、lambda、匿名委托 的使用【转】

    https://www.cnblogs.com/nicholashjh/p/7928205.html 首先定义一个泛型委托类型,如下: public delegate T Function<T& ...

  6. Asp.net WebApi版本控制

    有关web api的版本控制网上有很多,如Web API 版本控制的几种方式 Web API 版本化的介绍 但是具体的code并不多,或者说可以run的demo 不多. 版本控制如果项目一开始还好做关 ...

  7. Groupnet, Subnet, IP Pool的概念

    Groupnet是OneFS 8.0新引入的network object,专门为了服务Multi-Tenancy而创建,目的是让OneFS可以同时地处理多套网络配置. 如果用户不需要使用multi-t ...

  8. 热修复 DexPosed AOP Xposed MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  9. 老猪带你玩转自定义控件三——sai大神带我实现ios 8 时间滚轮控件

    ios 8 的时间滚轮控件实现了扁平化,带来很好用户体验,android没有现成控件,小弟不才,数学与算法知识不过关,顾十分苦恼,幸好在github上找到sai大神实现代码,甚为欣喜,顾把学习这个控件 ...

  10. 赋值操作符、复制构造函数、析构函数、static成员练习

    /** * 定义一个Employee类,包含雇员名字和一个唯一的雇员标识,为该类定义默认构造函数和参数为表示 * 雇员名字的string构造函数.如果该类需要复制构造函数或赋值操作符,实现这些函数 * ...