支持分布式的id生成器

import java.util.concurrent.atomic.AtomicInteger;

/**
* 这里的位是从高位说起的,第一位说的是符号位。
* 1bit + 41bit + 17bit + 5bit
* 第1bit固定是0 符号位不动 。
* 第2bit到第42bit使用时间蹉,精确到毫秒 41bit。 使用年限是69年
* 第43bit到第59bit使用自增的序列号 17bit 可用序列号最大131071个,说明一毫秒我们可以生成131071个不同的序列号。
* 第60bit到第64bit使用机器码 5bit 可以使系统可以分布式,最大分布式数量是32台机子。
* @author pdy
*/
public class IDGennerator {

//最大17bit的序列号是131071
private final static int max_orderNo = 131071;
//用于生成序列号
private AtomicInteger orderNo;
//机器码 (0-31)
private final static long machineCode = 31l;
//时间戳的掩码
private final static long time_code = Long.MAX_VALUE >>> 22;



public IDGennerator() {
orderNo = new AtomicInteger(0);
}

public long genneratorId(){
/**
* 时间戳
* 1、先去掉高23bit,保留当前时间的低41bit
* 2、将0到41bit移到高位去
*/
long currentTimeMillis = (System.currentTimeMillis() & time_code) << 22;

/**
* 序列号自增1和获取
*/
int orderNo = this.orderNo.incrementAndGet();
if(orderNo > max_orderNo){
//如果超过了最大序列号 则重置为0
if(!this.orderNo.compareAndSet(orderNo, 0)){
//这里使用cas操作,所以不需要加锁 1、操作失败了 则表示别的线程已经更改了数据,则直接进行自增并获取则可以了
orderNo = this.orderNo.incrementAndGet();
} else {
//操作成功后,则序列号为0了
orderNo = 0;
}
}
//符号位(1)bit、时间戳(2~42)bit | 序列号(43~59)bit | 机器码(60~64)bit
currentTimeMillis = currentTimeMillis | (orderNo << 14 >>> 9) | machineCode;
return currentTimeMillis;
}


//升级的版本

package com.hengyunsoft.util;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.concurrent.atomic.AtomicInteger;

/**
* 1bit + 41bit + 17bit + 5bit
* | | | |
* | | | |
* 符合位 时间戳(毫秒) 序列号 机器码
* 第1bit固定是0 符号位不动 。
* 第2bit到第42bit使用时间蹉,精确到毫秒 41bit。 使用年限是69年
* 第43bit到第59bit使用自增的序列号 17bit 可用序列号最大131071个,说明一毫秒我们可以生成131071个不同的序列号。
* 第60bit到第64bit使用机器码 5bit 可以使系统可以分布式,最大分布式数量是32台机子。
* @author pdy
*/
public class SnowflakeIDGenerate implements IIDGenerate<Long>{

//最大17bit的序列号是131071
private final static int max_orderNo = 131071;
//用于生成序列号
private AtomicInteger orderNo;
//机器码 (0-31)
private final long machineCode;
//时间戳的掩码
private final static long time_code = Long.MAX_VALUE >>> 22;
/**
* 2015-01-01 00:00:00
* 1420041600210
* 因为我们的生成器可以使用69年,而我们想在这些时间里面,生成出来的id是逐渐自增的。
* 所以我这里指定了从什么时候开始使用id生成器。
*/
private final long startTime = 1420041600210L;
public SnowflakeIDGenerate(final long machineCode) {
if( 0 > machineCode || machineCode > 31){
throw new IllegalArgumentException("请注意,1、机器码在多台机器或应用间是不允许重复的!2、机器码取值仅仅在0~31之间");
}
this.machineCode = machineCode;
orderNo = new AtomicInteger(0);
}

public Long generate(){
/**
* 时间戳
* 1、先去掉高23bit,保留当前时间的低41bit
* 2、将0到41bit移到高位去
*/
long currentTimeMillis = time_code & (System.currentTimeMillis() - startTime) << 22;

/**
* 序列号自增1和获取
*/
int orderNo = this.orderNo.incrementAndGet();
if(orderNo > max_orderNo){
//如果超过了最大序列号 则重置为0
if(!this.orderNo.compareAndSet(orderNo, 0)){
//这里使用cas操作,所以不需要加锁 1、操作失败了 则表示别的线程已经更改了数据,则直接进行自增并获取则可以了
orderNo = this.orderNo.incrementAndGet();
} else {
//操作成功后,则序列号为0了
orderNo = 0;
}
}
//符号位(1)bit、时间戳(2~42)bit | 序列号(43~59)bit | 机器码(60~64)bit
return currentTimeMillis | (orderNo << 14 >>> 9) | machineCode;
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值