/**
* distribute id generate algorithm
*
* @author rick.huang
* @version 1.0
* @date 2020/12/11 14:02
*/publicclassSnowflakeIdUtil{/**
* start time stamp (2020-01-01)
*/privatestaticfinallong startTimeStamp =1577808000000L;/**
* bytes code for work machine, 1~1023
*/privatestaticfinalint workerIdBits =10;/**
* bytes code for db
*/privatestaticfinalint datacenterIdBits =0;/**
* max number of worker
*/privatestaticfinalint maxWorkerId =~(-1<< workerIdBits);/**
* max number of db
*/privatestaticfinalint maxDatacenterId =~(-1<< datacenterIdBits);/**
* local sequence id length
*/privatestaticfinalint sequenceBits =12;/**
* worker id bytes offset
*/privatestaticfinalint workerIdShift = sequenceBits;/**
* db id bytes offset
*/privatestaticfinalint datacenterIdShift = sequenceBits + workerIdBits;/**
* time stamp bytes offset
*/privatestaticfinalint timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;/**
* max sequence id value
*/privatestaticfinalint sequenceMask =~(-1<< sequenceBits);/**
* worker identity, value 0 not used as identity
*/privatestaticint workerId =0;/**
* db identity, not necessary
*/privatestaticint datacenterId;/**
* atomic integer, volatile is not useful here
*/privatestaticfinal AtomicInteger sequence =newAtomicInteger(0);/**
* last used time stamp
*/privatestaticfinal AtomicLong nextTimeStamp =newAtomicLong(Clock.systemUTC().millis());/**
* init snowflake id util, this method showed just call one time
*
* @param id worker identity
*/publicstaticvoidinit(int id){if(id > maxWorkerId || id <0){thrownewIllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));}
workerId = id;}/**
* get next id
*
* @return SnowflakeId
*/publicstaticlongnextId(){if(workerId ==0)thrownewRuntimeException("snowflake util need init first");int id = sequence.getAndIncrement();long timeStamp = nextTimeStamp.get();if(id > sequenceMask){
sequence.compareAndSet(id +1,0);
id = sequence.getAndIncrement();
timeStamp = nextTimeStamp.incrementAndGet();}return((timeStamp - startTimeStamp)<< timestampLeftShift)//|(datacenterId << datacenterIdShift)//|(workerId << workerIdShift)//| id;}}