java獲取唯一時間戳Id.多執行緒保證唯一性
阿新 • • 發佈:2019-02-04
工程裡有獲取唯一時間戳作為id的需求,想了想用樂觀鎖cas實現,自旋.
cas原子性操作獲得了絕對唯一的時間戳(系統時間:納秒版本).單機有效,不能分散式呼叫.
public class AtomicTimeStamp { private AtomicLong timeMills = new AtomicLong(0); private static AtomicLong at = new AtomicLong(0); public Long getNextNaos(){ while (true){ long currentTimeMillis = System.nanoTime(); long currentMill = timeMills.get(); if(currentTimeMillis > currentMill && timeMills.compareAndSet(currentMill, currentTimeMillis)){ return currentTimeMillis; //返回唯一時間戳 } } } public static void main(String[] args) { AtomicTimeStamp stamp = new AtomicTimeStamp(); ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(100, 150, 200, TimeUnit.MILLISECONDS, new PriorityBlockingQueue<>(100),new ThreadFactoryBuilder().build()); long l = System.currentTimeMillis(); //開啟三個執行緒測試成功性,at自增,測試10S會有多少個成功的 poolExecutor.execute(()->{ while (true){ stamp.getNextNaos(); at.getAndIncrement(); long l1 = System.currentTimeMillis(); if(l1 > l + 10000 & l1<l+10010){ System.out.println(at.longValue()); } } }); poolExecutor.execute(()->{ while (true){ stamp.getNextNaos(); at.getAndIncrement(); long l1 = System.currentTimeMillis(); if (l1 > l + 10000 & l1 < l + 10010) { System.out.println(at.longValue()); } } }); poolExecutor.execute(()->{ while (true){ stamp.getNextNaos(); at.getAndIncrement(); long l1 = System.currentTimeMillis(); if (l1 > l + 10000 & l1 < l + 10010) { System.out.println(at.longValue()); } } }); } }
後面是新的要求,按照yyyyMMddHHmmssSSS… 的格式獲取唯一
private static AtomicLong atomicTimeMills = new AtomicLong(0); private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"); public static String getNextTime() { while (true) { long currentMill = atomicTimeMills.get(); Long currentTimeMillis = Long.parseLong(LocalDateTime.now().format(formatter) + System.nanoTime()%100); if (currentTimeMillis > currentMill && atomicTimeMills.compareAndSet(currentMill, currentTimeMillis)) { return currentTimeMillis.toString(); } } }