java如何根據(jù)時間戳生成有序ID
引言
我們常用的主鍵有這么幾種
1. 數(shù)據(jù)庫自增主鍵,比如mysql的autoincrement,這種插入快,但是識別度不高
2. uuid 這個號稱是全球唯一的,但是無序,沒有實際意義,只能保證唯一
3. 時間戳,這種在分布式的場景下就需要考慮更多種情況
4. 雪花算法 snow flake ,分布式全局唯一主鍵,很牛,但是我覺得用起來也挺麻煩哈哈哈
所以在并發(fā)情況沒那么大的時候用一個工具類搞定,我就是這么懶
工具類
@Slf4j
public class NumUtil {
private static long tmpID = 0;
private static final long LOCK_TIME = 1;
private static final long INCREASE_STEP = 1;
private static SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmssSSS");
private static final Lock LOCK = new ReentrantLock();
public static long nextPkId() throws InterruptedException {
//當前:(年、月、日、時、分、秒、毫秒)
long timeCount;
if (LOCK.tryLock(LOCK_TIME, TimeUnit.SECONDS)) {
timeCount = Long.parseLong(sdf.format(new Date()));
try {
if (tmpID < timeCount) {
tmpID = timeCount;
} else {
tmpID += INCREASE_STEP;
timeCount = tmpID;
}
return timeCount;
} finally {
LOCK.unlock();
}
} else {
log.error("lock failed");
return nextPkId();
}
}
}
貼上代碼,這里用了當前時間,精確到毫秒級,如果有需要的話可以在實例化timeCount的時候乘以10或者100 1000之類的,這個看大家,然后加上鎖,防止線程不安全的情況,加鎖失敗的時候遞歸,再來一次。
也可以使用synchronized做成同步方法,當中的區(qū)別下次再討論。
有評論說宕機會導致tmpID歸0導致已經(jīng)使用過超出當前時間的ID,所以持久化這個tmpID也是可以的。
但這也就是在并發(fā)沒那么高的情況下才使用這種方法,一般并發(fā)場景下還是分布式鎖+推特的雪花算法解決。
測試
public static void numTest() {
ExecutorService executorService = Executors.newCachedThreadPool();
int n = 10000;
List<Long> list = new ArrayList<>();
CountDownLatch latch = new CountDownLatch(n);
for (int i = 0; i < n; i++) {
executorService.execute(() -> {
//執(zhí)行業(yè)務請求
try {
list.add(NumUtil.nextPkId());
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
});
}
try {
// 一定記得加上timeout時間,防止阻塞主線程
latch.await(3000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
log.error(e.getMessage());
}
//4.等待所有子任務完成,組裝內(nèi)容
while (list.size() < n) {
log.info("集合長度 >>> {}",list.size());
}
//5.關(guān)閉線程池
executorService.shutdown();
for (Long aLong : list) {
System.out.println(aLong);
}
}
然后噼里啪啦打印了一萬個ID,沒有重復的,一秒以內(nèi)生成

結(jié)論
當然這種只是為了單體或者是并發(fā)沒有高到那么離譜的場景下使用,效率我覺得還不錯,分布式的場景下可能需要用到redis的自增來計數(shù)以達到數(shù)據(jù)安全的效果
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家
相關(guān)文章
Spring Security獲取用戶認證信息的實現(xiàn)流程
Spring Security是一個能夠為基于Spring的企業(yè)應用系統(tǒng)提供聲明式的安全訪問控制解決方案的安全框架。它提供了一組可以在Spring應用上下文中配置的Bean,充分利用了Spring IoC,DI和AOP功能,為應用系統(tǒng)提供聲明式的安全訪問控制功能2022-12-12
win10 eclipse配置環(huán)境變量的教程圖解
本文通過圖文并茂的形式給大家介紹了win10 eclipse配置環(huán)境變量的方法,非常不錯,具有一定的參考借鑒價值,需要的朋友參考下吧2018-07-07
springboot @validated List校驗失效問題
這篇文章主要介紹了springboot @validated List校驗失效問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07
springboot動態(tài)加載jar包動態(tài)配置實例詳解
這篇文章主要給大家介紹了關(guān)于springboot動態(tài)加載jar包動態(tài)配置的相關(guān)資料,在項目開發(fā)的過程中,有時候需要動態(tài)靈活的加載某個jar包并執(zhí)行其里面的方法的時候,需要的朋友可以參考下2023-11-11
SpringCloud組件之Eureka Server詳細啟動過程及說明
這篇文章主要介紹了SpringCloud組件之Eureka Server詳細啟動過程及說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01

