Snowflake Package; / ** * Twitter_Snowflake <br> * Snowflake following structure (with each section - apart): <br> * 0 - 0 0000000000 0000000000 0000000000 0000000000 - 0000000000 - 000000000000 <br> * bit identifier. 1, since the the basic type is signed long in Java, the most significant bit is a sign bit, 0 is a positive number, negative number is 1, so the id is usually a positive number, the most significant bit is <br> 0 * 41 is truncated bit time (milliseconds), attention , 41 cut-off time is not a time stored in the current cut-off time, but the difference between the storage time of the cut-off (cut-off current time - starting time cut) * the value obtained), where the start time of a truncated, generally we id generator time started, the program specified by our (the following procedure IdWorker startTime attribute class below). Cut-off time 41, 69 may be used in, in = T (1L << 41 is) / (1000L * 60 * 60 * 24 * 365) = 69 <br> * 10-bit data bit machine, can be deployed in 1024 nodes, and including 5 datacenterId <br> 5 workerId * 12 sequence count within milliseconds, the count of sequence number 12 of each support node per millisecond (the same machine, the same cut-off time) to produce the ID number 4096 <br > * add up to just 64 for a Long type. <br> * / Public class SnowflakeIdWorkerTest { // Fields =========== ============================== ================================ / ** start time cut (2015-01-01) * / Private Final Long = 1420041600000L twepoch; / **-digit share of the machine id * / Private Final Long workerIdBits = 5L; / ** id share data identifying the number of bits * / Private Final Long datacenterIdBits = 5L; / ** the maximum supported machine id, result is 31 (the shift algorithm can quickly calculate the maximum number of decimal binary number can represent several) * / Private Long maxWorkerId Final -1L = ^ (-1L << workerIdBits); / ** support the maximum data identification id, the result is * 31 is / Private Long maxDatacenterId Final -1L = ^ (-1L << datacenterIdBits); / ** sequence representing the median id * / Private Long sequenceBits Final = 12L; / ** machine ID 12 to the left * / Final workerIdShift = sequenceBits Long Private; / ** id identification data to the left by 17 (12 + 5) * / Private Long datacenterIdShift = Final sequenceBits + workerIdBits; / ** time to cut the left 22 (5 + 5 + 12 ) * / Private Long timestampLeftShift = Final workerIdBits sequenceBits + + datacenterIdBits; / ** generating a mask sequence, here 4095 (0b111111111111 = 0xFFF = 4095) * / Private Long sequenceMask Final -1L = ^ (-1L << sequenceBits) ; / * work machine ID (~ 31 is 0) * / Private Long workerId; / * a data center ID (~ 31 is 0) * / Private Long datacenterId; / ** milliseconds sequence (0 ~ 4095) * / Private Long = 0L Sequence; / ** previously generated ID sectional time * / Private Long LastTimestamp = -1L; //==============================Constructors===================================== /** * 构造函数 * @param workerId 工作ID (0~31) * @param datacenterId 数据中心ID (0~31) */ public SnowflakeIdWorkerTest(long workerId, long datacenterId) { if (workerId > maxWorkerId || workerId < 0) { throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); } if (datacenterId > maxDatacenterId || datacenterId < 0) { throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); } = workerId this.workerId; } // if it is generated at the same time, it is performed within milliseconds sequence = datacenterId this.datacenterId; } // Methods ========== ============================== ================================ / ** * get the next ID (which is thread-safe) * @ SnowflakeId return * / public nextId the synchronized Long () { Long TIMEGEN timestamp = (); // if the current time is less than the timestamp of the last generation ID, indicating the system clock backoff time should be thrown over this if (timestamp <lastTimestamp) { the throw a RuntimeException new new ( String.format ( "Clock Moved Backwards ID for refusing to Generate% D milliseconds.", LastTimestamp - timestamp)); IF (LastTimestamp == timestamp) { Sequence = (+ Sequence. 1) & sequenceMask; // ms sequence the overflow IF (Sequence == 0) { // blocking the next millisecond, obtain a new timestamp timestamp = tilNextMillis (LastTimestamp); } } // change timestamp, sequence milliseconds reset the else { Sequence 0L =; } // ID generated time last cut LastTimestamp = timestamp; // shifted and ORed to fight consisting of 64-bit ID with the return ((timestamp - twepoch) << timestampLeftShift) // | (datacenterId < <datacenterIdShift) // * @param lastTimestamp time cut previously generated ID * @return current timestamp | (workerId << workerIdShift) // | Sequence; } / ** * obstruction to the next millisecond, until a new timestamp / ** * test / * / Protected Long tilNextMillis (Long LastTimestamp) { Long TIMEGEN timestamp = (); the while (timestamp <= LastTimestamp) { timestamp TIMEGEN = (); } return timestamp; } / ** * returns the current time in milliseconds * @ return current time (ms) * / protected Long TIMEGEN () { return System.currentTimeMillis (); } // ========================== ==== Test ============================================= static void main public (String [] args) { SnowflakeIdWorkerTest idWorker new new SnowflakeIdWorkerTest = (0, 0); for (int I = 0; I <1000; I ++) { long id = idWorker.nextId(); System.out.println(Long.toBinaryString(id)); System.out.println(id); } } }