package com.iplatform.base; public class IdUtil { private static IdUtil instance = new IdUtil(0); public static IdUtil getInstance() { return instance; } public static long generateId() { return instance.nextId(); } private final static long MACHINE_BIT = 5; // max 31 private final static long SEQUENCE_BIT = 8; // 256/10ms /** * mask/max value */ private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT); private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT); private final static long MACHINE_LEFT = SEQUENCE_BIT; private final static long TIMESTMP_LEFT = MACHINE_BIT + SEQUENCE_BIT; private long machineId; private long sequence = 0L; private long lastStmp = -1L; private IdUtil(long machineId) { if (machineId > MAX_MACHINE_NUM || machineId < 0) { throw new IllegalArgumentException( "machineId can't be greater than " + MAX_MACHINE_NUM + " or less than 0"); } this.machineId = machineId; } /** * generate new ID * * @return */ public synchronized long nextId() { long currStmp = getTimestamp(); if (currStmp < lastStmp) { throw new RuntimeException("Clock moved backwards. Refusing to generate id"); } if (currStmp == lastStmp) { sequence = (sequence + 1) & MAX_SEQUENCE; if (sequence == 0L) { currStmp = getNextTimestamp(); } } else { sequence = 0L; } lastStmp = currStmp; return currStmp << TIMESTMP_LEFT // | machineId << MACHINE_LEFT // | sequence; } private long getNextTimestamp() { long mill = getTimestamp(); while (mill <= lastStmp) { mill = getTimestamp(); } return mill; } private long getTimestamp() { // per 10ms return System.currentTimeMillis() / 10;// 10ms } }