public class KeyWorker { private final static long twepoch = 12888349746579L; // machine identification digits private final static long workerIdBits = 5L; // data center identification digits private final static long datacenterIdBits = 5L; // increment the number of bits within milliseconds private final static long sequenceBits = 12L; // shift left the machine ID 12 private final static long workerIdShift = sequenceBits; // ID data center left 17 private final static long datacenterIdShift = sequenceBits + workerIdBits; // time in milliseconds left 22 private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; // sequence mask, ensure sequnce we not exceed the upper limit private final static long sequenceMask = -1L ^ (-1L << sequenceBits); // last timestamp private static long lastTimestamp = -1L; //sequence private long sequence = 0L; // server ID private long workerId = 1L; private static long workerMask = -1L ^ (-1L << workerIdBits); // encoding process private long processId = 1L; private static long processMask = -1L ^ (-1L << datacenterIdBits); private static KeyWorker keyWorker = null; static { keyWorker = new KeyWorker(); } public static synchronized long nextId() { return keyWorker.getNextId(); } private KeyWorker() { // get the machine code this.workerId = this.getMachineNum(); // Get the coding process RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean(); this.processId = Long.valueOf(runtimeMXBean.getName().split("@")[0]).longValue(); // avoid exceeding the maximum coding this.workerId = workerId & workerMask; this.processId = processId & processMask; } public synchronized long getNextId() { // Get the timestamp long timestamp = timeGen(); // If the timestamp is less than the last time stamp error if (timestamp < lastTimestamp) { try { throw new Exception("Clock moved backwards. Refusing to generate id for " + (lastTimestamp - timestamp) + " milliseconds"); } catch (Exception e) { e.printStackTrace (); } } // If the time stamp and time stamp the same as last time if (lastTimestamp == timestamp) { // current within milliseconds, +1, and sequenceMask ensure that sequence will not exceed the upper limit sequence = (sequence + 1) & sequenceMask; if (sequence == 0) { // current in the millisecond count is full, the next second waiting timestamp = tilNextMillis(lastTimestamp); } } else { sequence = 0; } lastTimestamp = timestamp; // offset ID generate a final composition ID, and returns the ID long nextId = ((timestamp - twepoch) << timestampLeftShift) | (processId << datacenterIdShift) | (workerId << workerIdShift) | sequence; return nextId; } /** * Get the timestamp and timestamp again until the acquisition of different existing * * @Param lastTimestamp * @Return a timestamp next */ private long tilNextMillis(final long lastTimestamp) { long timestamp = this.timeGen(); while (timestamp <= lastTimestamp) { timestamp = this.timeGen(); } return timestamp; } private long timeGen() { return System.currentTimeMillis(); } /** * Get machine code * * @return */ private long getMachineNum() { long machinePiece; StringBuilder sb = new StringBuilder(); Enumeration<NetworkInterface> e = null; try { e = NetworkInterface.getNetworkInterfaces(); } catch (SocketException e1) { e1.printStackTrace (); } while (e.hasMoreElements()) { NetworkInterface ni = e.nextElement(); sb.append(ni.toString()); } machinePiece = sb.toString().hashCode(); return machinePiece; } }