package com.doumee.core.utils; import org.apache.logging.log4j.util.Strings; import java.util.UUID; /** * A utility to generate id using various strategies. * * @author Guang YANG * @version 1.0 */ public class ID { private static final SnowflakeIdGenerator snowflake = new SnowflakeIdGenerator(0); /** * Generate a random guid string of 32 byte. */ public static String nextGUID() { return UUID.randomUUID().toString().replace("-", Strings.EMPTY).toUpperCase(); } /** * Generate a random uuid string of 36 byte. */ public static String nextUUID() { return UUID.randomUUID().toString(); } /** * Generate a long number of 20 bit which is monotonically increasing by each call. */ public static long nextSnowflakeId() { return snowflake.nextId(); } public static class SnowflakeIdGenerator { private final long workerIdBits = 10L; private final long maxWorkerId = -1L ^ (-1L << workerIdBits); private final long sequenceBits = 12L; private final long workerIdShift = sequenceBits; private final long timestampLeftShift = sequenceBits + workerIdBits; private final long sequenceMask = -1L ^ (-1L << sequenceBits); private long workerId; private long sequence = 0L; private long lastTimestamp = -1L; public SnowflakeIdGenerator(long workerId) { if (workerId > maxWorkerId || workerId < 0) { throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); } this.workerId = workerId; } public synchronized long nextId() { long timestamp = System.currentTimeMillis(); if (timestamp < lastTimestamp) { throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); } if (lastTimestamp == timestamp) { sequence = (sequence + 1) & sequenceMask; if (sequence == 0) { timestamp = tilNextMillis(lastTimestamp); } } else { sequence = 0L; } lastTimestamp = timestamp; return (timestamp << timestampLeftShift) | (workerId << workerIdShift) | sequence; } protected long tilNextMillis(long lastTimestamp) { long timestamp = System.currentTimeMillis(); while (timestamp <= lastTimestamp) { timestamp = System.currentTimeMillis(); } return timestamp; } } }