(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. 小程序页面跳转传参参数值为url时参数时 会出现丢失

    当参数的值为url的时候,  ?号   _  下划线   等等 都会被 截取掉,看不到,  这样在 另一个页面 options中  截取的url就不完全 let url="http://ba ...

  2. jieba库的使用与词频统计

    1.词频统计 (1)词频分析是对文章中重要词汇出现的次数进行统计与分析,是文本 挖掘的重要手段.它是文献计量学中传统的和具有代表性的一种内容分析方法,基本原理是通过词出现频次多少的变化,来确定热点及其 ...

  3. 用 Java 解密 C# 加密的数据(DES)(转)

    今天遇到java解密url的问题.我们的系统要获取外部传过来的URL,URL是采用 DES 算法对消息进行加密,再用 BASE64 编码.不过对方系统是用 C# 写的. 在网上搜了几篇文章终于找到一篇 ...

  4. 【原创开源应用第5期】基于RL-USB+RL-FlashFS的外挂U盘解决方案

    说明:1.RL-USB外挂U盘的例子,最近太多网友咨询,再不做一个例子就说不过去了.此例子为此而生.2.RTX及其所有中间件基本都做例子了,就差这个USB Host功能了,这次算是补上,所有功能基本已 ...

  5. 使用SIP Servlet为Java EE添加语音功能

    会话发起协议(Session Initiation Protocol,SIP)是一种信号传输协议,用于建立.修改和终止两个端点之间的会话.SIP 可用于建立 两方呼叫.多方呼叫,或者甚至 Intern ...

  6. [Swift]LeetCode901. 股票价格跨度 | Online Stock Span

    Write a class StockSpanner which collects daily price quotes for some stock, and returns the span of ...

  7. Mysql的两种“排名第几且有可能为空的记录”写法(力扣176)

    编写一个 SQL 查询,获取 Employee 表中第二高的薪水(Salary) . +----+--------+ | Id | Salary | +----+--------+ | 1 | 100 ...

  8. 【mysql】Date和String的互相转换(DATE_FORMAT & STR_TO_DATE)

    1.Date  ——>  String 使用的函数:DATE_FORMAT(date,format)     date:需要转换的日期       format:格式化的样式 format样式整 ...

  9. 【Storm篇】--Storm 容错机制

    一.前述 Storm容错机制相比其他的大数据组件做的非常不错. 二.具体原因 结合Storm集群架构图: 我们的程序提交流程如下:   其中各个组件的作用如下: Nimbus资源调度任务分配接收jar ...

  10. lambda表达式中的排序问题

    新月新气象,10月第一篇,这也是我工作的第一天,这一篇文章我们要讲到lambda的排序问题 我是这样排序的 var list = DB.company.OrderBy(x=>x.isfreeze ...