15位自增ID生成工具类

首先感谢https://blog.csdn.net/liuyanglglg/article/details/103480436作者的思路,然后进行了改进.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Random;

/**
* 15位自增CODE生成工具
*/
public class SuperCodeUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(SuperCodeUtil.class);
/**
* 核销码表示字符,0~9,A~Z,去除0、O、I、L 4个易混淆的字符还是32位
*/
private final static char[] DIGITS = {
'1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'M',
'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z'};
//时间戳位数,占9位
private final static int STAMP_LEN = 9;
//随机数位数,占4位
private final static int RANDOM_LEN = 4;
//随机数最大值
private final static int MAX_RANDOM_INT = (int) (Math.pow(DIGITS.length, RANDOM_LEN) - 1);
//上次时间戳值
private static long last_Stmp = 0L;
//随机对象
private static final Random RANDOM = new Random();
//同步锁对象
private static Object lockObject = new Object();

/**
* 默认生成方法
* 生成15位时间戳+随机数生成的编码
*
* @return
*/
public static String genSuperCode() {
return genSuperCode(0, 0);
}

/**
* 生成15位时间戳+随机数生成的编码
*
* @param datacenterId 数据中心ID -1<datacenterId<DIGITS.length
* @param machineId 机器ID -1<machineId<DIGITS.length
* @return
*/
public static String genSuperCode(int datacenterId, int machineId) {
if (datacenterId > DIGITS.length - 1) datacenterId = 0;
if (machineId > DIGITS.length - 1) machineId = 0;
StringBuilder sbSuperCode = new StringBuilder();
sbSuperCode.append(DIGITS[Math.abs(datacenterId)]);
sbSuperCode.append(DIGITS[Math.abs(machineId)]);
sbSuperCode.append(genStampCode());
sbSuperCode.append(genRandomCode());
return sbSuperCode.toString();
}

/**
* 生成9位时间戳字符
*
* @return
*/
private static String genStampCode() {
long timestamp =System.currentTimeMillis();
synchronized (lockObject)
{
while (timestamp <= last_Stmp) {
try {
//防止CPU占用过高
lockObject.wait(10);
} catch (InterruptedException e) {
LOGGER.error("SuperCodeUtil ERROR:{}", e);
}
timestamp = System.currentTimeMillis();
}
last_Stmp = timestamp;
}
String stampCode = convert2String(timestamp);
StringBuilder sb = new StringBuilder();
//补齐位
for (int i = stampCode.length(); i < STAMP_LEN; i++) {
sb.append(DIGITS[0]);
}
return sb.toString() + stampCode;
}

/**
* 生成4位随机数字符
*
* @return
*/
private static String genRandomCode() {

final int random = nextInt(0, MAX_RANDOM_INT);
String randomCode = convert2String(random);
StringBuilder sb = new StringBuilder();
//补齐位
for (int i = randomCode.length(); i < RANDOM_LEN; i++) {
sb.append(DIGITS[0]);
}
return sb.toString() + randomCode;
}

/**
* 把十进制转换成DIGITS.length定义的进制
*
* @param i
* @return
*/
private static String convert2String(long i) {
char[] buf = new char[10];
int charPos = 10 - 1;
while (i > DIGITS.length - 1) {
buf[charPos--] = DIGITS[(int) (i % DIGITS.length)];
i /= DIGITS.length;
}
buf[charPos--] = DIGITS[(int) i];
return new String(buf).trim();
}

/**
* 根据范围生成随机数
*
* @param startInclusive
* @param endExclusive
* @return
*/
private static int nextInt(int startInclusive, int endExclusive) {
return startInclusive == endExclusive ? startInclusive : startInclusive + RANDOM.nextInt(endExclusive - startInclusive);
}

/*
public static void main(String[] args) throws InterruptedException {
List<String> list1= Lists.newArrayList();
List<String> list2= Lists.newArrayList();
Thread t1=new Thread(()->{
for(int i=1000;i<1999;i++){
list1.add(SuperCodeUtil.genSuperCode());
}
});
Thread t2=new Thread(()->{
for(int i=2000;i<2999;i++){
list2.add(SuperCodeUtil.genSuperCode());
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(JSON.toJSONString(list1.stream().collect(Collectors.joining(","))));
System.out.println(JSON.toJSONString(list2.stream().collect(Collectors.joining(","))));
}
*/

}

 

posted @ 2020-11-13 14:39  疯癫大圣  阅读(907)  评论(0编辑  收藏  举报