package com.eas.util; import java.util.concurrent.atomic.AtomicLong; /** * * @author mg */ public class IdGenerator { private static final int COUNTER_DIGITS = 100; private static final AtomicLong ID = new AtomicLong(System.currentTimeMillis() * COUNTER_DIGITS); private static final int LONG_COUNTER_DIGITS = 1000000; private static final AtomicLong LONG_ID = new AtomicLong(System.currentTimeMillis() * LONG_COUNTER_DIGITS); public static long genId() { return generate(ID, COUNTER_DIGITS); } public static long genLongId() { return generate(LONG_ID, LONG_COUNTER_DIGITS); } public static String genStringId() { return String.valueOf(genLongId()); } private static long generate(AtomicLong aLastId, int aCounterDigits) { long newId; long id; do { id = aLastId.get(); long idMillis = id / aCounterDigits;// Note! Truncation of fractional part is here. if (idMillis == System.currentTimeMillis()) { long oldCounter = id - idMillis * aCounterDigits; long newCounter = oldCounter + 1; if (newCounter == aCounterDigits) { // Spin lock with maximum duration of one millisecond ... long newMillis; do { newMillis = System.currentTimeMillis(); } while (newMillis == idMillis); newId = newMillis * aCounterDigits; } else { newId = idMillis * aCounterDigits + newCounter; } } else { newId = System.currentTimeMillis() * aCounterDigits; } } while (!aLastId.compareAndSet(id, newId)); return newId; } }