1
0
mirror of synced 2025-12-26 15:07:57 +08:00

重命名 java 为 Java

This commit is contained in:
yitter
2021-03-13 22:55:22 +08:00
committed by Gitee
parent fc33f62dca
commit 2d517eebd1
15 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
/*
* 版权属于yitter(yitter@126.com)
* 开源地址https://gitee.com/yitter/idgenerator
*/
package com.yitter.contract;
public interface IIdGenerator {
long newLong() throws IdGeneratorException;
}

View File

@@ -0,0 +1,9 @@
/*
* 版权属于yitter(yitter@126.com)
* 开源地址https://gitee.com/yitter/idgenerator
*/
package com.yitter.contract;
public interface ISnowWorker {
long nextId() throws IdGeneratorException;
}

View File

@@ -0,0 +1,28 @@
/*
* 版权属于yitter(yitter@126.com)
* 开源地址https://gitee.com/yitter/idgenerator
*/
package com.yitter.contract;
public class IdGeneratorException extends RuntimeException {
public IdGeneratorException() {
super();
}
public IdGeneratorException(String message) {
super(message);
}
public IdGeneratorException(Throwable cause) {
super(cause);
}
public IdGeneratorException(String message, Throwable cause) {
super(message, cause);
}
public IdGeneratorException(String msgFormat, Object... args) {
super(String.format(msgFormat, args));
}
}

View File

@@ -0,0 +1,69 @@
/*
* 版权属于yitter(yitter@126.com)
* 开源地址https://gitee.com/yitter/idgenerator
*/
package com.yitter.contract;
/**
* 雪花算法使用的参数
* 此处代码不采用 get/set 那种冗长的写法
*/
public class IdGeneratorOptions {
/**
* 雪花计算方法
* 1-漂移算法|2-传统算法默认1
*/
public short Method = 1;
/**
* 开始时间
* 不能超过当前系统时间
*/
public long StartTime = 0;
/**
* 机器码,必须由外部系统设置
* 与 WorkerIdBitLength 有关系
*/
public short WorkerId = 0;
/**
* 机器码位长
* 范围2-21要求序列数位长+机器码位长不超过22
* 建议范围6-12。
*/
public byte WorkerIdBitLength = 6;
/**
* 序列数位长
* 范围2-21要求序列数位长+机器码位长不超过22
* 建议范围6-14。
*/
public byte SeqBitLength = 6;
/**
* 最大序列数(含)
* 由SeqBitLength计算的最大值
*/
public short MaxSeqNumber = 0;
/**
* 最小序列数(含)
* 默认11不小于5不大于MaxSeqNumber-2
*/
public short MinSeqNumber = 11;
/**
* 最大漂移次数(含)
* 默认2000推荐范围500-10000与计算能力有关
*/
public short TopOverCostCount = 2000;
public IdGeneratorOptions() {
}
public IdGeneratorOptions(short workerId) {
WorkerId = workerId;
}
}

View File

@@ -0,0 +1,51 @@
/*
* 版权属于yitter(yitter@126.com)
* 开源地址https://gitee.com/yitter/idgenerator
*/
package com.yitter.contract;
/**
* Id生成时回调参数
*/
public class OverCostActionArg {
/**
* 事件类型
* 1-开始2-结束8-漂移
*/
public int ActionType = 0;
/**
* 时间戳
*/
public long TimeTick = 0;
/**
* 机器码
*/
public short WorkerId = 0;
/**
*
*/
public int OverCostCountInOneTerm = 0;
/**
* 漂移期间生产ID个数
*/
public int GenCountInOneTerm = 0;
/**
* 漂移周期
*/
public int TermIndex = 0;
public OverCostActionArg(short workerId, long timeTick, int actionType, int overCostCountInOneTerm, int genCountWhenOverCost, int index) {
ActionType = actionType;
TimeTick = timeTick;
WorkerId = workerId;
OverCostCountInOneTerm = overCostCountInOneTerm;
GenCountInOneTerm = genCountWhenOverCost;
TermIndex = index;
}
}

View File

@@ -0,0 +1,247 @@
/*
* 版权属于yitter(yitter@126.com)
* 开源地址https://gitee.com/yitter/idgenerator
*/
package com.yitter.core;
import com.yitter.contract.ISnowWorker;
import com.yitter.contract.IdGeneratorException;
import com.yitter.contract.IdGeneratorOptions;
import com.yitter.contract.OverCostActionArg;
public class SnowWorkerM1 implements ISnowWorker {
/**
* 基础时间
*/
protected final long StartTimeUtc;
/**
* 机器码
*/
protected final short WorkerId;
/**
* 机器码位长
* (机器码+序列数<=22位
*/
protected final byte WorkerIdBitLength;
/**
* 自增序列数位长
* (机器码+序列数<=22位
*/
protected final byte SeqBitLength;
/**
* 最大序列数(含此值)
* 超过最大值就会从MinSeqNumber开始
*/
protected final int MaxSeqNumber;
/**
* 最小序列数(含此值)
*/
protected final short MinSeqNumber;
/**
* 最大漂移次数
*/
protected final int TopOverCostCount;
protected final byte _TimestampShift;
protected final static byte[] _SyncLock = new byte[0];
protected short _CurrentSeqNumber;
protected long _LastTimeTick = -1L;
protected long _TurnBackTimeTick = -1L;
protected boolean _IsOverCost = false;
protected int _OverCostCountInOneTerm = 0;
protected int _GenCountInOneTerm = 0;
protected int _TermIndex = 0;
public SnowWorkerM1(IdGeneratorOptions options) {
WorkerId = options.WorkerId;
WorkerIdBitLength = options.WorkerIdBitLength == 0 ? 6 : options.WorkerIdBitLength;
SeqBitLength = options.SeqBitLength == 0 ? 6 : options.SeqBitLength;
MaxSeqNumber = options.MaxSeqNumber > 0 ? options.MaxSeqNumber : (int) Math.pow(2, SeqBitLength);
MinSeqNumber = options.MinSeqNumber;
TopOverCostCount = options.TopOverCostCount;
StartTimeUtc = options.StartTime != 0 ? options.StartTime : 1582136402000L;
_TimestampShift = (byte) (WorkerIdBitLength + SeqBitLength);
_CurrentSeqNumber = options.MinSeqNumber;
}
private void DoGenIdAction(OverCostActionArg arg) {
}
private void BeginOverCostCallBack(long useTimeTick) {
// if (GenAction == null) {
// return;
// }
//
// DoGenIdAction(new OverCostActionArg(
// WorkerId,
// useTimeTick,
// 1,
// _OverCostCountInOneTerm,
// _GenCountInOneTerm,
// _TermIndex));
}
private void EndOverCostCallBack(long useTimeTick) {
if (_TermIndex > 10000) {
_TermIndex = 0;
}
//
// if (GenAction == null) {
// return;
// }
//
// DoGenIdAction(new OverCostActionArg(
// WorkerId,
// useTimeTick,
// 2,
// _OverCostCountInOneTerm,
// _GenCountInOneTerm,
// _TermIndex));
}
private void TurnBackCallBack(long useTimeTick) {
// if (GenAction == null) {
// return;
// }
//
// DoGenIdAction(new OverCostActionArg(
// WorkerId,
// useTimeTick,
// 8,
// _OverCostCountInOneTerm,
// _GenCountInOneTerm,
// _TermIndex));
}
private long NextOverCostId() {
long currentTimeTick = GetCurrentTimeTick();
if (currentTimeTick > _LastTimeTick) {
EndOverCostCallBack(currentTimeTick);
_LastTimeTick = currentTimeTick;
_CurrentSeqNumber = MinSeqNumber;
_IsOverCost = false;
_OverCostCountInOneTerm = 0;
_GenCountInOneTerm = 0;
return CalcId(_LastTimeTick);
}
if (_OverCostCountInOneTerm >= TopOverCostCount) {
EndOverCostCallBack(currentTimeTick);
_LastTimeTick = GetNextTimeTick();
_CurrentSeqNumber = MinSeqNumber;
_IsOverCost = false;
_OverCostCountInOneTerm = 0;
_GenCountInOneTerm = 0;
return CalcId(_LastTimeTick);
}
if (_CurrentSeqNumber > MaxSeqNumber) {
_LastTimeTick++;
_CurrentSeqNumber = MinSeqNumber;
_IsOverCost = true;
_OverCostCountInOneTerm++;
_GenCountInOneTerm++;
return CalcId(_LastTimeTick);
}
_GenCountInOneTerm++;
return CalcId(_LastTimeTick);
}
private long NextNormalId() throws IdGeneratorException {
long currentTimeTick = GetCurrentTimeTick();
if (currentTimeTick > _LastTimeTick) {
_LastTimeTick = currentTimeTick;
_CurrentSeqNumber = MinSeqNumber;
return CalcId(_LastTimeTick);
}
if (_CurrentSeqNumber > MaxSeqNumber) {
BeginOverCostCallBack(currentTimeTick);
_TermIndex++;
_LastTimeTick++;
_CurrentSeqNumber = MinSeqNumber;
_IsOverCost = true;
_OverCostCountInOneTerm++;
_GenCountInOneTerm = 1;
return CalcId(_LastTimeTick);
}
if (currentTimeTick < _LastTimeTick) {
if (_TurnBackTimeTick < 1) {
_TurnBackTimeTick = _LastTimeTick - 1;
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
TurnBackCallBack(_TurnBackTimeTick);
return CalcTurnBackId(_TurnBackTimeTick);
}
return CalcId(_LastTimeTick);
}
private long CalcId(long useTimeTick) {
long result = ((useTimeTick << _TimestampShift) +
((long) WorkerId << SeqBitLength) +
(int) _CurrentSeqNumber);
_CurrentSeqNumber++;
return result;
}
private long CalcTurnBackId(long useTimeTick) {
long result = ((useTimeTick << _TimestampShift) +
((long) WorkerId << SeqBitLength) + 0);
_TurnBackTimeTick--;
return result;
}
protected long GetCurrentTimeTick() {
long millis = System.currentTimeMillis();
return millis - StartTimeUtc;
}
protected long GetNextTimeTick() {
long tempTimeTicker = GetCurrentTimeTick();
while (tempTimeTicker <= _LastTimeTick) {
tempTimeTicker = GetCurrentTimeTick();
}
return tempTimeTicker;
}
@Override
public long nextId() {
synchronized (_SyncLock) {
return _IsOverCost ? NextOverCostId() : NextNormalId();
}
}
}

View File

@@ -0,0 +1,41 @@
/*
* 版权属于yitter(yitter@126.com)
* 开源地址https://gitee.com/yitter/idgenerator
*/
package com.yitter.core;
import com.yitter.contract.IdGeneratorException;
import com.yitter.contract.IdGeneratorOptions;
public class SnowWorkerM2 extends SnowWorkerM1 {
public SnowWorkerM2(IdGeneratorOptions options) {
super(options);
}
@Override
public long nextId() {
synchronized (_SyncLock) {
long currentTimeTick = GetCurrentTimeTick();
if (_LastTimeTick == currentTimeTick) {
if (_CurrentSeqNumber++ > MaxSeqNumber) {
_CurrentSeqNumber = MinSeqNumber;
currentTimeTick = GetNextTimeTick();
}
} else {
_CurrentSeqNumber = MinSeqNumber;
}
if (currentTimeTick < _LastTimeTick) {
throw new IdGeneratorException("Time error for {0} milliseconds", _LastTimeTick - currentTimeTick);
}
_LastTimeTick = currentTimeTick;
long result = ((currentTimeTick << _TimestampShift) + ((long) WorkerId << SeqBitLength) + (int) _CurrentSeqNumber);
return result;
}
}
}

View File

@@ -0,0 +1,85 @@
/*
* 版权属于yitter(yitter@126.com)
* 开源地址https://gitee.com/yitter/idgenerator
*/
package com.yitter.idgen;
import com.yitter.contract.ISnowWorker;
import com.yitter.contract.IdGeneratorException;
import com.yitter.contract.IdGeneratorOptions;
import com.yitter.contract.IIdGenerator;
import com.yitter.core.SnowWorkerM1;
import com.yitter.core.SnowWorkerM2;
public class DefaultIdGenerator implements IIdGenerator {
private final ISnowWorker _SnowWorker;
public DefaultIdGenerator(IdGeneratorOptions options) throws IdGeneratorException {
if (options == null)
{
throw new IdGeneratorException("options error.");
}
if (options.StartTime > System.currentTimeMillis())
{
throw new IdGeneratorException("StartTime error.");
}
if (options.SeqBitLength + options.WorkerIdBitLength > 22)
{
throw new IdGeneratorException("errorWorkerIdBitLength + SeqBitLength <= 22");
}
double maxWorkerIdNumber = Math.pow(2, options.WorkerIdBitLength) - 1;
if (options.WorkerId < 1 || options.WorkerId > maxWorkerIdNumber)
{
throw new IdGeneratorException("WorkerId error. (range:[1, " + maxWorkerIdNumber + "]");
}
if (options.SeqBitLength < 2 || options.SeqBitLength > 21)
{
throw new IdGeneratorException("SeqBitLength error. (range:[2, 21])");
}
double maxSeqNumber = Math.pow(2, options.SeqBitLength) - 1;
if (options.MaxSeqNumber < 0 || options.MaxSeqNumber > maxSeqNumber)
{
throw new IdGeneratorException("MaxSeqNumber error. (range:[1, " + maxSeqNumber + "]");
}
double maxValue = maxSeqNumber - 2;
if (options.MinSeqNumber < 5 || options.MinSeqNumber > maxValue)
{
throw new IdGeneratorException("MinSeqNumber error. (range:[5, " + maxValue + "]");
}
switch (options.Method)
{
case 1:
_SnowWorker = new SnowWorkerM1(options);
break;
case 2:
_SnowWorker = new SnowWorkerM2(options);
break;
default:
_SnowWorker = new SnowWorkerM1(options);
break;
}
if (options.Method == 1)
{
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public long newLong() {
return _SnowWorker.nextId();
}
}

View File

@@ -0,0 +1,45 @@
/*
* 版权属于yitter(yitter@126.com)
* 开源地址https://gitee.com/yitter/idgenerator
*/
package com.yitter.idgen;
import com.yitter.contract.IdGeneratorException;
import com.yitter.contract.IdGeneratorOptions;
import com.yitter.contract.IIdGenerator;
/**
* 这是一个调用的例子,默认情况下,单机集成者可以直接使用 NewId()。
*/
public class IdHelper {
private static IIdGenerator idGenInstance = null;
public static IIdGenerator getIdGenInstance()
{
return idGenInstance;
}
/**
* 设置参数,建议程序初始化时执行一次
* @param options
*/
public static void setIdGenerator(IdGeneratorOptions options) throws IdGeneratorException {
idGenInstance = new DefaultIdGenerator(options);
}
/**
* 生成新的Id
* 调用本方法前,请确保调用了 SetIdGenerator 方法做初始化。
* @return
*/
public static long nextId() throws IdGeneratorException {
if (idGenInstance == null)
{
idGenInstance = new DefaultIdGenerator(new IdGeneratorOptions((short)1));
}
return idGenInstance.newLong();
}
}

View File

@@ -0,0 +1,31 @@
package com.yitter.test;
import com.yitter.contract.IIdGenerator;
public class GenTest {
private IIdGenerator IdGen;
private int GenIdCount;
private int WorkerId;
public GenTest(IIdGenerator idGen, int genIdCount, int workerId) {
GenIdCount = genIdCount;
IdGen = idGen;
WorkerId = workerId;
}
public void GenStart() {
long start = System.currentTimeMillis();
for (int i = 0; i < GenIdCount; i++) {
long id = IdGen.newLong();
}
long end = System.currentTimeMillis();
long time = end - start;
System.out.println("++++++++++++++++++++++++++++++++++++++++WorkerId: "
+ WorkerId + ", total: " + time + " ms");
}
}

View File

@@ -0,0 +1,57 @@
package com.yitter.test;
import com.yitter.contract.IdGeneratorOptions;
import com.yitter.contract.IIdGenerator;
import com.yitter.idgen.DefaultIdGenerator;
import com.yitter.idgen.IdHelper;
public class StartUp {
/**
* 测试结果:
* (1)1W并发方法 1只要 1ms.而方法 2 要 180ms。
* (2)5W并发方法 1只要 9ms.而方法 2 要 900ms。
* [不同CPU可能结果有差异但相对大小不变]
* 默认配置下最佳性能是5W/s-8W/s
*/
final static int genIdCount = 50000;
//1-漂移算法2-传统算法
final static short method = 1;
public static void main(String[] args) {
IdGeneratorOptions options = new IdGeneratorOptions();
//options.TopOverCostCount = 10000;
// options.WorkerIdBitLength = 6;
// options.SeqBitLength = 9;
// options.MinSeqNumber = 11;
// options.MaxSeqNumber = 200;
options.Method = method;
options.WorkerId = 1;
options.StartTime = 1582206693000L; // (2020-2-20)
IIdGenerator IdGen = new DefaultIdGenerator(options);
GenTest genTest = new GenTest(IdGen, genIdCount, options.WorkerId);
// 首先测试一下 IdHelper 方法获取单个Id
IdHelper.setIdGenerator(options);
long newId = IdHelper.nextId();
System.out.println("=====================================");
System.out.println("这是用方法 " + method + " 生成的 Id" + newId);
// 然后循环测试一下,看看并发请求时的耗时情况
try {
while (true) {
genTest.GenStart();
Thread.sleep(1000); // 每隔1秒执行一次GenStart
System.out.println("Hello World!");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}