UUID組成部分
1+分片標(biāo)識(shí)符+年月日+遞增數(shù)字
其中遞增數(shù)字,長(zhǎng)度不夠前面補(bǔ)0
實(shí)現(xiàn)
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.atomic.AtomicLong;
public class UUIDGenerator {
// 分片號(hào),占4位
private static String slotId;
// 是否調(diào)用init()方法進(jìn)行初始化
private static boolean inited = false;
private static int date;
private static AtomicLong incre = new AtomicLong(1);
private static final String DataFormat = "yyMMdd";
private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>();
private static DateFormat getDateFormat() {
DateFormat df = threadLocal.get();
if (df == null) {
df = new SimpleDateFormat(DataFormat);
threadLocal.set(df);
}
return df;
}
/**
* 按指定格式對(duì)Date所持有的時(shí)間進(jìn)行格式化
* @param date
* @return
*/
private static int format(Date date) {
return Integer.valueOf(getDateFormat().format(date));
}
/**
* 指定時(shí)間戳所在日期的0點(diǎn)時(shí)間戳
* @param millis
* @return
*/
private static long zeroTime(long millis) {
Calendar calendar = Calendar.getInstance();
// TimeZone curTimeZone = TimeZone.getTimeZone("GMT+8");
// Calendar calendar = Calendar.getInstance(curTimeZone);
calendar.setTimeInMillis(millis);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTimeInMillis();
}
/**
* 在使用前調(diào)初始化
*
* @param slotId
*/
public static void init(int slotId) {
if (inited) {
return;
}
if (slotId >= 1000) {
throw new RuntimeException("Slot ID must be smaller than 10000");
}
UUIDGenerator.slotId = String.format("%03d", slotId);
inited = true;
}
/**
* 生成UUID
* @return
*/
public static long generate() {
if (!inited) {
throw new RuntimeException("The init() method must be called first");
}
int currDate = format(new Date());
if (currDate != date) {
synchronized (UUIDGenerator.class) {
if (currDate != date) {
//自增偏移量,初始值設(shè)置為當(dāng)日的秒數(shù),防止因重啟或其他原因造成生成的ID重復(fù)
long offset = 1+(System.currentTimeMillis() - zeroTime(System.currentTimeMillis()))/1000;
System.out.println("offset: "+offset);
incre.set(offset);
date = currDate;
}
}
}
String uuid = String.format("1%s%d%09d", slotId, date, incre.getAndIncrement());
return Long.valueOf(uuid);
}
public static void main(String[] args) throws InterruptedException {
UUIDGenerator.init(5);
int jmax = 1000;
CountDownLatch countDownLatch = new CountDownLatch(10);
HashSet<Long> uuids = new HashSet<>();
for (int i = 0; i < 10; i++) {
new Thread(() -> {
for (int j = 0; j < jmax; j++) {
long uuid = UUIDGenerator.generate();
System.out.println(uuid);
uuids.add(uuid);
}
countDownLatch.countDown();
}).start();
}
countDownLatch.await();
if(uuids.size() != jmax*10) {
System.out.println("UUID generate error ...... !!!");
}else {
System.out.println("UUID generate success!!!");
}
}
}
總結(jié)
每日可保存上億的UUID生成,足夠項(xiàng)目使用。