(1)需要导入的包

主要用在格式化日FastDateFormat.getInstance("yyyyMMddHHmmssSSS");

<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>

(2)IdGenerator类

import org.apache.commons.lang3.time.FastDateFormat;
import java.net.InetAddress;
import java.net.UnknownHostException; /**
* 与snowflake算法区别,返回字符串id,占用更多字节,但直观从id中看出生成时间
* 改写了生成时间的format方法
* @Project concurrency
*/ public enum IdGenerator { INSTANCE;
private long workerId; //用ip地址最后几个字节标示
private long datacenterId = 0L; //可配置在properties中,启动时加载,此处默认先写成0
private long sequence = 0L;
private long workerIdBits = 8L; //节点ID长度
private long datacenterIdBits = 2L; //数据中心ID长度,可根据时间情况设定位数
private long sequenceBits = 12L; //序列号12位
private long workerIdShift = sequenceBits; //机器节点左移12位
private long datacenterIdShift = sequenceBits + workerIdBits; //数据中心节点左移14位
private long sequenceMask = -1L ^ (-1L << sequenceBits); //4095
private long lastTimestamp = -1L;
private static final FastDateFormat FAST_DATE_FORMAT = FastDateFormat.getInstance("yyyyMMddHHmmssSSS"); IdGenerator(){
workerId = 0x000000FF & getLastIP();
}
public synchronized String 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只有12bit,所以和sequenceMask相与一下,去掉高位
sequence = (sequence + 1) & sequenceMask;
//判断是否溢出,也就是每毫秒内超过4095,当为4096时,与sequenceMask相与,sequence就等于0
if (sequence == 0) {
timestamp = tilNextMillis(lastTimestamp); //自旋等待到下一毫秒
}
} else {
sequence = 0L; //如果和上次生成时间不同,重置sequence,就是下一毫秒开始,sequence计数重新从0开始累加
}
lastTimestamp = timestamp;
long suffix = (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence;
//String datePrefix = DateFormatUtils.format(timestamp, "yyyyMMddHHmmssSSS");
String datePrefix = FAST_DATE_FORMAT.format(timestamp);
return datePrefix + suffix;
} protected long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
} protected long timeGen() {
return System.currentTimeMillis();
} private byte getLastIP(){
byte lastip = 0;
try{
InetAddress ip = InetAddress.getLocalHost();
byte[] ipByte = ip.getAddress();
lastip = ipByte[ipByte.length - 1];
} catch (UnknownHostException e) {
e.printStackTrace();
}
return lastip;
} }

(3)使用举例

String id = IdGenerator.INSTANCE.nextId()

永不重复的id生成器的更多相关文章

  1. IDUtil 永不重复的ID

    package com.xxx.common.util; import java.util.Random; /** * 各种id生成策略 * * @version 1.0 */ public clas ...

  2. IOS ID生成器

    // // IdGenerator.m // Copyright (c) 2014年 青岛拓宇网络科技有限公司. All rights reserved. // #import "IdGen ...

  3. js生成一个不重复的ID的函数的进化之路

    在MongoDB中的ObjectID,可以理解为是一个不会重复的ID,这里有个链接http://blog.csdn.net/xiamizy/article/details/41521025感兴趣可以去 ...

  4. 分布式ID生成器 zz

    简介 这个是根据twitter的snowflake来写的.这里有中文的介绍. 如上图所示,一个64位ID,除了最左边的符号位不用(固定为0,以保证生成的ID都是正数),还剩余63位可用. 下面的代码与 ...

  5. 游戏服务器ID生成器组件

    游戏服务器程序中,经常需要生成全局的唯一ID号,这个功能很常用,本文将介绍一种通用ID生成组件.游戏服务器程序中使用此组件的场景有: 创建角色时,为其分配唯一ID 创建物品时,每个物品需要唯一ID 创 ...

  6. ID生成器详解

    概述 ID 生成器也叫发号器,它的主要目的就是"为一个分布式系统的数据object产生一个唯一的标识",但其实在一个真实的系统里可能也可以承担更多的作用.概括起来主要有以下几点: ...

  7. twitter的ID生成器的snowFlake算法的自造版

    snowFlake算法在生成ID时特别高效,可参考:https://segmentfault.com/a/1190000011282426 SnowFlake算法生成id的结果是一个64bit大小的整 ...

  8. c#分布式ID生成器

    c#分布式ID生成器   简介 这个是根据twitter的snowflake来写的.这里有中文的介绍. 如上图所示,一个64位ID,除了最左边的符号位不用(固定为0,以保证生成的ID都是正数),还剩余 ...

  9. ID 生成器 雪花算法

    https://blog.csdn.net/wangming520liwei/article/details/80843248 ID 生成器 雪花算法 2018年06月28日 14:58:43 wan ...

随机推荐

  1. Ajax级联选择框

    Ajax级联选择框 级联选择框常用与比较负责的网页开发,例如实现的商品添加页面中,需要选择商品的分类,而分类信息又有层次,例如大分类和小分类就是两层级联,在用户选择商品所属大类时,所属小类的内容需要根 ...

  2. Springboot Selenide UI 自动化测试

    标题中的Selenide 并没有拼错,确实不是selenium Selenium做UI自动化,可以参考我其他的blog: Selenium做自动化最好要封装起来,否则对于元素的等待,页面的加载会使得自 ...

  3. 关于H5页面的测试总结与分析

    一.时下最流行的H5到底是什么 ?有什么优势和劣势? (1)H5 即HTML5,其实就是:移动端Web页面. (2)优势: H5可以跨平台使用,开发成本相对较低 H5可随时上线就更新版本,适合快速迭代 ...

  4. Python 远程开机

    用 Python 关机你肯定听过或者实践过,那么用 Python 开机呢?这是一个神奇的方法,教你如何用 Python 来开机. 本文目标 远程开机原理 Python 远程开机代码实现 Python ...

  5. [Swift]LeetCode29. 两数相除 | Divide Two Integers

    Given two integers dividend and divisor, divide two integers without using multiplication, division ...

  6. [Swift]LeetCode105. 从前序与中序遍历序列构造二叉树 | Construct Binary Tree from Preorder and Inorder Traversal

    Given preorder and inorder traversal of a tree, construct the binary tree. Note:You may assume that ...

  7. [Swift]LeetCode200.岛屿的个数 | Number of Islands

    Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surro ...

  8. Docker for windows : 安装linux

    一.Linux 1.拉取镜像 docker pull hub.c..com/library/oraclelinux:latest 2.创建linux容器 C:\Users\K-Jso>docke ...

  9. Shader 入门笔记(二) CPU和GPU之间的通信,渲染流水线

    渲染流水线 1)应用阶段(CPU处理) 首先,准备好场景数据(摄像机位置,视锥体,模型和光源等) 接着,做粗粒度剔除工作. 最后,设置好每个模型的渲染状态(使用的材质,纹理,shader等) 这一阶段 ...

  10. 《HelloGitHub月刊》第 05 期

    <HelloGitHub>第 05 期 兴趣是最好的老师,<HelloGitHub>就是帮你找到兴趣! 欢迎各路人士加入本项目,丰富月刊的内容,也可以直接在Issue(需要登录 ...