RandomUtil | IDWorker | NoCenter | |
---|---|---|---|
第一次 | 0.187s | 0.036s | 0.324s |
第二次 | 0.121s | 0.05s | 0.305s |
第三次 | 0.131s | 0.036s | 0.283s |
100000次测试生成ID
RandomUtil | IDWorker | NoCenter | |
---|---|---|---|
第一次 | 0.678s | 0.191s | 0.922s |
第二次 | 0.678s | 0.201s | 0.846s |
第三次 | 0.684s | 0.197s | 0.932s |
RandomUtil | IDWorker | NoCenter | |
---|---|---|---|
第一次 | 4.442s | 1.933s | 4.387s |
第二次 | 4.316s | 1.864s | 4.571s |
第三次 | 4.25s | 1.782s | 4.499s |
10000000次测试生成ID
RandomUtil | IDWorker | NoCenter | |
---|---|---|---|
第一次 | 37.291s | 16.664s | 37.096s |
第二次 | 37.105s | 16.583s | 37.096s |
第三次 | 37.44s | 16.648s | 37.096s |
CODE
RandomUtil
public class RandomUtil { private static String[] chars = new String[]{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}; // private static String[] chars = new String[] { "0", "1", "2", "3", "4", "5", // "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", // "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", // "W", "X", "Y", "Z" }; public static String generateShortUuid() { StringBuffer shortBuffer = new StringBuffer(); String uuid = UUID.randomUUID().toString().replace("-", ""); for (int i = 0; i < 4; i++) { String str = uuid.substring(i * 4, i * 4 + 4); int x = Integer.parseInt(str, 16); shortBuffer.append(chars[x % 36]); } return String.valueOf(new RandomUtil(1, 2).nextId() + shortBuffer.toString()); } /** * 起始的时间戳 */ private final static long START_STMP = 1420041600000L; /** * 序列号占用的位数 */ private final static long SEQUENCE_BIT = 12L; /** * 机器标识占用的位数 */ private final static long MACHINE_BIT = 5L; /** * 数据中心占用的位数 */ private final static long DATACENTER_BIT = 5L; /** * 每一部分的最大值 */ private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT); 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 DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT; private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT; /** * 数据中心 */ private long datacenterId; /** * 机器标识 */ private long machineId; /** * 序列号 */ private long sequence = 0L; /** * 上一次时间戳 */ private long lastStmp = -1L; public RandomUtil(long datacenterId, long machineId) { if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) { throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0"); } if (machineId > MAX_MACHINE_NUM || machineId < 0) { throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0"); } this.datacenterId = datacenterId; this.machineId = machineId; } /** * 产生下一个ID * * @return */ public synchronized long nextId() { long currStmp = getNewstmp(); if (currStmp < lastStmp) { throw new RuntimeException("Clock moved backwards. Refusing to generate userId"); } if (currStmp == lastStmp) { //相同毫秒内,序列号自增 sequence = (sequence + 1) & MAX_SEQUENCE; //同一毫秒的序列数已经达到最大 if (sequence == 0L) { currStmp = getNextMill(); } } else { //不同毫秒内,序列号置为0 sequence = 0L; } lastStmp = currStmp; //时间戳部分 return (currStmp - START_STMP) << TIMESTMP_LEFT //数据中心部分 | datacenterId << DATACENTER_LEFT //机器标识部分 | machineId << MACHINE_LEFT //序列号部分 | sequence; } private long getNextMill() { long mill = getNewstmp(); while (mill <= lastStmp) { mill = getNewstmp(); } return mill; } private long getNewstmp() { return System.currentTimeMillis(); } public static void main(String[] args) { long startTime = System.currentTimeMillis(); for (int i = 0; i < 10000000; i++) { System.out.println(RandomUtil.generateShortUuid()); } long endTime = System.currentTimeMillis(); float excTime = (float) (endTime - startTime) / 1000; System.out.println("执行时间:" + excTime + "s"); } }
IDWorker(推荐)
public class IDWorker { /** * 起始的时间戳 */ private final static long START_STMP = 1480166465631L; /** * 每一部分占用的位数 */ private final static long SEQUENCE_BIT = 12; //序列号占用的位数 private final static long MACHINE_BIT = 5; //机器标识占用的位数 private final static long DATACENTER_BIT = 5;//数据中心占用的位数 /** * 每一部分的最大值 */ private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT); 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 DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT; private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT; private long datacenterId; //数据中心 private long machineId; //机器标识 private long sequence = 0L; //序列号 private long lastStmp = -1L;//上一次时间戳 public IDWorker(long datacenterId, long machineId) { if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) { throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0"); } if (machineId > MAX_MACHINE_NUM || machineId < 0) { throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0"); } this.datacenterId = datacenterId; this.machineId = machineId; } /** * 产生下一个ID * * @return */ public synchronized long nextId() { long currStmp = getNewstmp(); 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 = getNextMill(); } } else { //不同毫秒内,序列号置为0 sequence = 0L; } lastStmp = currStmp; return (currStmp - START_STMP) << TIMESTMP_LEFT //时间戳部分 | datacenterId << DATACENTER_LEFT //数据中心部分 | machineId << MACHINE_LEFT //机器标识部分 | sequence; //序列号部分 } private long getNextMill() { long mill = getNewstmp(); while (mill <= lastStmp) { mill = getNewstmp(); } return mill; } private long getNewstmp() { return System.currentTimeMillis(); } public static void main(String[] args) { long startTime = System.currentTimeMillis(); IDWorker idWorker = new IDWorker(2, 3); for (int i = 0; i < 10000000; i++) { System.out.println(idWorker.nextId()); } long endTime = System.currentTimeMillis(); float excTime = (float) (endTime - startTime) / 1000; System.out.println("执行时间:" + excTime + "s"); } }
OrderNoCenter
public class OrderNoCenter { private Logger logger = LoggerFactory.getLogger(OrderNoCenter.class); private static final String WORKERID_PATH = "/etc/workerId"; private OrderNoCenter() { } private static class OrderNoCenterHolder { private static OrderNoCenter instance = new OrderNoCenter(); } public static OrderNoCenter getInstance() { return OrderNoCenterHolder.instance; } /** * 节点 ID 默认取1 */ private long workerId = 1; /** * 序列id 默认取1 */ private long sequence = 1; /** * 机器标识位数 */ private final long workerIdBits = 10L; /** * 机器ID最大值 * 结果就是2的workerBits次方-1,能表示的最大数.全部1亦或10位0,就是0开头最后10位1 */ private final long maxWorkerId = -1L ^ (-1L << workerIdBits); /** * 毫秒内自增位 */ private final long sequenceBits = 12L; /** * 机器ID偏左移12位 */ private final long workerIdShift = sequenceBits; /** * 数据中心ID左移17位 */ private final long datacenterIdShift = sequenceBits + workerIdBits; private final long sequenceMask = -1L ^ (-1L << sequenceBits); /** * 时间毫秒左移22位 */ private final long timestampLeftShift = sequenceBits + workerIdBits; private long lastTimestamp = -1L; public void initParam() { // 从默认位置读取workerId,最大1024 try { File conf = new File(WORKERID_PATH); if (conf.exists()) { //这里引入common io或者直接自己写读取文件 String str = FileUtils.readFileToString(conf); workerId = Integer.parseInt(str); } else { logger.warn(" worker id not found,will use default value..."); } } catch (Exception e) { e.printStackTrace(); } logger.info(" worker id is {}", workerId); if (workerId < 0 || workerId > maxWorkerId) { throw new IllegalArgumentException("workerId is illegal: " + workerId); } } public long getWorkerId() { return workerId; } public long getTime() { return System.currentTimeMillis(); } public String create() { return nextNo(); } /** * 获取id 线程安全 * * @return */ private synchronized String nextNo() { long timestamp = timeGen(); // 时间错误 if (timestamp < lastTimestamp) { throw new IllegalStateException("Clock moved backwards."); } // 当前毫秒内,则+1 if (lastTimestamp == timestamp) { // 当前毫秒内计数满了,则等待下一秒 sequence = (sequence + 1) & sequenceMask; if (sequence == 0) { timestamp = tilNextMillis(lastTimestamp); } } else { sequence = 0; } lastTimestamp = timestamp; // ID偏移组合生成最终的ID,并返回ID,最大十位数 long id = ((timestamp % 1000) << timestampLeftShift) | (workerId << workerIdShift) | sequence; //建议使用common lang format //报错的话,可以替换为 String timestampStr = new SimpleDateFormat("yyyyMMddHHmmss").format(timestamp); return timestampStr + String.format("%010d", id); } /** * 等待下一个毫秒的到来 * * @param lastTimestamp * @return */ private long tilNextMillis(long lastTimestamp) { long timestamp = timeGen(); while (timestamp <= lastTimestamp) { timestamp = timeGen(); } return timestamp; } private long timeGen() { return System.currentTimeMillis(); } public static void main(String[] args) { long startTime = System.currentTimeMillis(); for (int i = 0; i < 10000000; i++) { System.out.println(OrderNoCenter.getInstance().create()); } long endTime = System.currentTimeMillis(); float excTime = (float) (endTime - startTime) / 1000; System.out.println("执行时间:" + excTime + "s"); } }
生成算法是从网上找的,非本人纯手撸!
在此感谢