uuidgenerator.java

来自「OpenJMS是一个开源的Java Message Service API 1.」· Java 代码 · 共 899 行 · 第 1/3 页

JAVA
899
字号
                }                if (_uuidsThisTick + 1 < _uuidsPerTick) {                    // Clock did not advance, but able to create more UUIDs                    // for this clock, proceed.                    ++_uuidsThisTick;                    break;                }                // Running out of UUIDs for the current clock tick, must                // wait until clock advances. Possible that clock did not                // advance in background, so try to synchronize it first.                clock = Clock.synchronize();                if (clock <= _lastClock) {                    // if (Configuration.verbose)                    //Logger.tyrex.debug(Messages.message("tyrex.uuid.fastHolding"));                    while (clock <= _lastClock) {                        // UUIDs generated too fast, suspend for a while.                        try {                            Thread.currentThread().sleep(Clock.getUnsynchTicks());                        } catch (InterruptedException except) {                        }                        clock = Clock.synchronize();                    }                }            }            // Modify Java clock (milliseconds) to UUID clock (100 nanoseconds).            // Add the count of uuids to low order bits of the clock reading,            // assuring we get a unique clock.            clock = (_lastClock + JAVA_UUID_CLOCK_DIFF) * 100 + _uuidsThisTick;            chars = new char[36];            // Add the low field of the clock (4 octets)            chars[0] = HEX_DIGITS[(int) ((clock >> 28) & 0x0F)];            chars[1] = HEX_DIGITS[(int) ((clock >> 24) & 0x0F)];            chars[2] = HEX_DIGITS[(int) ((clock >> 20) & 0x0F)];            chars[3] = HEX_DIGITS[(int) ((clock >> 16) & 0x0F)];            chars[4] = HEX_DIGITS[(int) ((clock >> 12) & 0x0F)];            chars[5] = HEX_DIGITS[(int) ((clock >> 8) & 0x0F)];            chars[6] = HEX_DIGITS[(int) ((clock >> 4) & 0x0F)];            chars[7] = HEX_DIGITS[(int) (clock & 0x0F)];            chars[8] = '-';            // Add the medium field of the clock (2 octets)            chars[9] = HEX_DIGITS[(int) ((clock >> 44) & 0x0F)];            chars[10] = HEX_DIGITS[(int) ((clock >> 40) & 0x0F)];            chars[11] = HEX_DIGITS[(int) ((clock >> 36) & 0x0F)];            chars[12] = HEX_DIGITS[(int) ((clock >> 32) & 0x0F)];            chars[13] = '-';            // Add the high field of the clock multiplexed with version number (2 octets)            chars[14] = HEX_DIGITS[(int) (((clock >> 60) & 0x0F) | UUID_VERSION_CLOCK_OCTET)];            chars[15] = HEX_DIGITS[(int) ((clock >> 56) & 0x0F)];            chars[16] = HEX_DIGITS[(int) ((clock >> 52) & 0x0F)];            chars[17] = HEX_DIGITS[(int) ((clock >> 48) & 0x0F)];            chars[18] = '-';            // Add the clock sequence and version identifier (2 octets)            chars[19] = _clockSeqOctet[0];            chars[20] = _clockSeqOctet[1];            chars[21] = _clockSeqOctet[2];            chars[22] = _clockSeqOctet[3];            chars[23] = '-';            // Add the node identifier (6 octets)            chars[24] = _nodeIdentifierOctet[0];            chars[25] = _nodeIdentifierOctet[1];            chars[26] = _nodeIdentifierOctet[2];            chars[27] = _nodeIdentifierOctet[3];            chars[28] = _nodeIdentifierOctet[4];            chars[29] = _nodeIdentifierOctet[5];            chars[30] = _nodeIdentifierOctet[6];            chars[31] = _nodeIdentifierOctet[7];            chars[32] = _nodeIdentifierOctet[8];            chars[33] = _nodeIdentifierOctet[9];            chars[34] = _nodeIdentifierOctet[10];            chars[35] = _nodeIdentifierOctet[11];        }        return chars;    }    /**     * Returns a time-based UUID as a character array. The UUID     * identifier is always 16 bytes long.     *     * @return A time-based UUID     */    public static byte[] createTimeUUIDBytes() {        long clock;        byte[] bytes;        long nextClock;        // Acquire lock to assure synchronized generation        synchronized (UUIDGenerator.class) {            clock = Clock.clock();            while (true) {                if (clock > _lastClock) {                    // Since we are using the clock interval for the UUID                    // space, we must make sure the next clock provides                    // sufficient room so UUIDs do not roll over.                    nextClock = _lastClock + (_uuidsThisTick / 100);                    if (clock <= nextClock) {                        clock = Clock.synchronize();                    }                    if (clock > nextClock) {                        // Clock reading changed since last UUID generated,                        // reset count of UUIDs generated with this clock.                        _uuidsThisTick = 0;                        _lastClock = clock;                        // Adjust UUIDs per tick in case the clock sleep ticks                        // have changed.                        _uuidsPerTick = Clock.getUnsynchTicks() * 100;                        break;                    }                }                if (_uuidsThisTick + 1 < _uuidsPerTick) {                    // Clock did not advance, but able to create more UUIDs                    // for this clock, proceed.                    ++_uuidsThisTick;                    break;                }                // Running out of UUIDs for the current clock tick, must                // wait until clock advances. Possible that clock did not                // advance in background, so try to synchronize it first.                clock = Clock.synchronize();                if (clock <= _lastClock) {                    // if (Configuration.verbose)                    // Logger.tyrex.debug(Messages.message("tyrex.uuid.fastHolding"));                    while (clock <= _lastClock) {                        // UUIDs generated too fast, suspend for a while.                        try {                            Thread.currentThread().sleep(Clock.getUnsynchTicks());                        } catch (InterruptedException ignore) {                        }                        clock = Clock.synchronize();                    }                }            }            // Modify Java clock (milliseconds) to UUID clock (100 nanoseconds).            // Add the count of uuids to low order bits of the clock reading,            // assuring we get a unique clock.            clock = (_lastClock + JAVA_UUID_CLOCK_DIFF) * 100 + _uuidsThisTick;            bytes = new byte[16];            // Add the low field of the clock (4 octets)            bytes[0] = (byte) ((clock >> 24) & 0xFF);            bytes[1] = (byte) ((clock >> 16) & 0xFF);            bytes[2] = (byte) ((clock >> 8) & 0xFF);            bytes[3] = (byte) (clock & 0xFF);            // Add the medium field of the clock (2 octets)            bytes[4] = (byte) ((clock >> 40) & 0xFF);            bytes[5] = (byte) ((clock >> 32) & 0xFF);            // Add the high field of the clock multiplexed with version            // number (2 octets)            bytes[6] = (byte) (((clock >> 60) & 0xFF)                | UUID_VERSION_CLOCK_BYTE);            bytes[7] = (byte) ((clock >> 48) & 0xFF);            // Add the clock sequence and version identifier (2 octets)            bytes[8] = _clockSeqByte[0];            bytes[9] = _clockSeqByte[1];            // Add the node identifier (6 octets)            bytes[10] = _nodeIdentifierByte[0];            bytes[11] = _nodeIdentifierByte[1];            bytes[12] = _nodeIdentifierByte[2];            bytes[13] = _nodeIdentifierByte[3];            bytes[14] = _nodeIdentifierByte[4];            bytes[15] = _nodeIdentifierByte[5];        }        return bytes;    }    /**     * Returns true if the UUID was created on this machine.     * Determines the source of the UUID based on the node     * identifier.     *     * @param uuid The UUID as a byte array     * @return True if created on this machine     */    public static boolean isLocal(byte[] uuid) {        if (uuid == null)            throw new IllegalArgumentException("Argument uuid is null");        if (uuid.length != 16)            return false;        return (uuid[10] == _nodeIdentifierByte[0] &&            uuid[11] == _nodeIdentifierByte[1] &&            uuid[12] == _nodeIdentifierByte[2] &&            uuid[13] == _nodeIdentifierByte[3] &&            uuid[14] == _nodeIdentifierByte[4] &&            uuid[15] == _nodeIdentifierByte[5]);    }    /**     * Initialise the generator     * <p>     * This method generates the node identifier and clock sequence, and     * sets {@link #_uuidsPerTick} to the number of UUIDs allowed per clock     * tick.     */    private static void initialize() {        // Random random = new SecureRandom();        Random random = new Random();        String nodeIdString;        long nodeIdLong;        String seqString;        int seqInt;        // Generate the node identifier, as we can't determine the IEEE 802        // address of the local host.        // As a result, it must have bit 48 set.        nodeIdLong = random.nextLong();        nodeIdLong = nodeIdLong | (1 << 47);        // Generate the clock sequence        seqInt = random.nextInt(1 << 12);        seqInt = seqInt & 0x1FFF;        // Convert clock sequence to 4 hexadecimal digits        _clockSeqOctet = new char[4];        _clockSeqOctet[0] = HEX_DIGITS[(int) ((seqInt >> 12) & 0x0F)];        _clockSeqOctet[1] = HEX_DIGITS[(int) ((seqInt >> 8) & 0x0F)];        _clockSeqOctet[2] = HEX_DIGITS[(int) ((seqInt >> 4) & 0x0F)];        _clockSeqOctet[3] = HEX_DIGITS[(int) (seqInt & 0x0F)];        _clockSeqByte = new byte[2];        _clockSeqByte[0] = (byte) ((seqInt >> 8) & 0xFF);        _clockSeqByte[1] = (byte) (seqInt & 0xFF);        // Need to mask UUID variant on clock sequence        _clockSeqOctet[0] = HEX_DIGITS[(int) ((seqInt >> 12) & 0x0F)            | UUID_VARIANT_OCTET];        _clockSeqByte[0] = (byte) (((seqInt >> 8) & 0xFF)            | UUID_VARIANT_BYTE);        // Convert node identifier to 12 hexadecimal digits        _nodeIdentifierOctet = new char[12];        for (int i = 0; i < 12; ++i) {            _nodeIdentifierOctet[i] =                HEX_DIGITS[(int) ((nodeIdLong >> ((11 - i) * 4)) & 0x0F)];        }        _nodeIdentifierByte = new byte[6];        for (int i = 0; i < 6; ++i) {            _nodeIdentifierByte[i] =                (byte) ((nodeIdLong >> ((5 - i) * 8)) & 0xFF);        }        // The number of UUIDs allowed per tick depends on the number of        // ticks between each advance of the clock, adjusted for 100        // nanosecond precision.        _uuidsPerTick = Clock.getUnsynchTicks() * 100;    }    static {        initialize();        // This makes sure we miss at least one clock tick, just to be safe.        _uuidsThisTick = _uuidsPerTick;        _lastClock = Clock.clock();    }    public static void main(String[] args) {        long clock;        HashSet hash;        String id;        int count = 1000000;        for (int i = 0; i < 10; ++i) {            System.out.println(create());        }        clock = System.currentTimeMillis();        hash = new HashSet(count / 100, 100);        for (int i = 0; i < count; ++i) {            if ((i % 10000) == 0)                System.out.println("Checked " + i);            id = create();            if (hash.contains(id))                System.out.println("Duplicate id " + id);            else                hash.add(id);        }        clock = System.currentTimeMillis() - clock;        System.out.println("Generated " + count + " UUIDs in " + clock + "ms");    }    /**     * An exception indicating the identifier is invalid and     * cannot be converted into an array of bytes.     */    public static class InvalidIDException extends Exception {        public InvalidIDException(String message) {            super(message);        }    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?