package com.walker.infrastructure.utils;
|
|
import com.walker.infrastructure.ServerId;
|
|
import java.util.UUID;
|
|
public abstract class NumberGenerator {
|
|
public static final long[] DIGIT_SIZE_TABLE = {9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999
|
, 9999999999L, 99999999999L, 999999999999L, 9999999999999L, 99999999999999L, 999999999999999L, 9999999999999999L
|
, 99999999999999999L, 999999999999999999L};
|
|
public static final int NANO_SIZE = 16;
|
|
public static final long getLongSequenceNumberNano(){
|
// LocalDateTime localDateTime = LocalDateTime.now();
|
// System.out.println("getNano = " + localDateTime.getNano());
|
// Clock clock = Clock.systemDefaultZone();
|
// Instant instant = Instant.now(); // or Instant.now();
|
// long seconds = instant.getEpochSecond();
|
// long nano = instant.getNano();
|
// return (seconds * 1000000000 + nano);
|
long nano = System.nanoTime();
|
if(nano < 0){
|
nano = Math.abs(nano);
|
}
|
long id = System.currentTimeMillis() + nano;
|
int idSize = getDigitBitSize(id);
|
if(idSize > NANO_SIZE){
|
// 超过16位,必须重新生成
|
id = System.currentTimeMillis() * 1000 + Long.parseLong(StringUtils.generateRandomNumber(3));
|
}
|
return id;
|
// return System.currentTimeMillis() + nano;
|
}
|
|
private static final int getDigitBitSize(long value){
|
for (int i = 0;; i++)
|
if (value <= DIGIT_SIZE_TABLE[i])
|
return i + 1;
|
}
|
|
/**
|
* 得到顺序数,此方法根据系统当前时间生成毫秒数。</p>
|
* 对于数据量不大(通常每秒钟小于1000)的访问可以使用。</br>
|
* 如果更大,可以使用<code>getSequenceNumber()</code>方法。
|
* @return
|
*/
|
public static final long getSequenceNumber(){
|
return System.currentTimeMillis();
|
}
|
|
/**
|
* 返回15位的数值,这是根据系统纳秒数生成的。
|
* @return
|
* @date 2015-07-12
|
* @date 2023-06-29 重写方法,是用毫秒与纳秒结合方式生成序列,因为纯纳秒方法与虚拟机启动有关,在虚拟机不停重启时仍然会重复
|
*/
|
public static final long getLongSequenceNumber(){
|
// long v = System.nanoTime();
|
// if(v < 0){
|
// return Math.abs(v);
|
// }
|
// return v;
|
return getLongSequenceNumberNano();
|
}
|
|
/**
|
* 返回纳秒值长整形数字,转为字符串。
|
* @return
|
* @date 2022-08-12
|
* @date 2023-10-07 生成支持集群的字符串ID,通过本机配置的主机ID(serverId)
|
* @date 2023-10-13 由于id在文件命名中不能使用冒号,所以变更为下划线。
|
*/
|
public static final String getLongSequenceId(){
|
// return String.valueOf(getLongSequenceNumber());
|
return new StringBuilder(ServerId.getId())
|
.append(StringUtils.STRING_UNDERLINE).append(NumberGenerator.getLongSequenceNumber())
|
.append(StringUtils.STRING_UNDERLINE).append(StringUtils.generateRandomNumber(5)).toString();
|
}
|
|
/**
|
* 产生32位随机字符串
|
* @return
|
*/
|
public static String generatorHexUUID(){
|
return UUID.randomUUID().toString();
|
}
|
|
/**
|
* @param args
|
*/
|
public static void main(String[] args) {
|
// for(int i=0; i<3; i++){
|
// long startTime = System.nanoTime();
|
// long result = getSequenceNumber();
|
// System.out.println(result);
|
// System.out.println("times: " + (System.nanoTime()-startTime));
|
// }
|
// System.out.println("long sequence: " + getLongSequenceNumber());
|
//
|
// long value = getSequenceNumber();
|
// Date date = new Date(value);
|
// System.out.println(date);
|
|
// List<Integer> list = new ArrayList<>();
|
long startTime = 0;
|
long nanoSecond = 0;
|
for(int i=0; i<30; i++){
|
startTime = System.nanoTime();
|
nanoSecond = getLongSequenceNumberNano();
|
System.out.println(nanoSecond + ", total time = " + (System.nanoTime() - startTime));
|
}
|
|
long mod = System.nanoTime() % 10;
|
System.out.println(mod);
|
}
|
|
}
|