package com.gkhy.safePlatform.commons.utils.idService; public class IdGenerateUtil { // 起始的时间戳 private final static long START_STMP = 1577808000000L; //2020-01-01 // 每一部分占用的位数,就三个 private final static long SEQUENCE_BIT = 10; //序列号占用的位数 private final static long TABLE_BIT = 7; //数据库表占用的位数 private final static long BIZ_BIT = 5; //业务占用的位数 // 每一部分最大值 private final static long MAX_BIZ_NUM = -1L ^ (-1L << BIZ_BIT); private final static long MAX_TABLE_NUM = -1L ^ (-1L << TABLE_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 + TABLE_BIT; private final static long TIMESTMP_LEFT = DATACENTER_LEFT + BIZ_BIT; private long bizId; //业务标识 private long tableId; //数据库表标识 private long sequence = 0L; //序列号 private long lastStmp = -1L; //上一次时间戳 public IdGenerateUtil() { } // public SnowFlakeUtil(long bizId, long tableId) { // if (bizId > MAX_BIZ_NUM || bizId < 0) { // throw new IllegalArgumentException("bizId can't be greater than MAX_BIZ_NUM or less than 0"); // } // if (tableId > MAX_TABLE_NUM || tableId < 0) { // throw new IllegalArgumentException("tableId can't be greater than MAX_TABLE_NUM or less than 0"); // } // this.bizId = bizId; // this.tableId = tableId; // } public synchronized long nextId(long bizId, long tableId) { if (bizId > MAX_BIZ_NUM || bizId < 0) { throw new IllegalArgumentException("bizId can't be greater than MAX_BIZ_NUM or less than 0"); } if (tableId > MAX_TABLE_NUM || tableId < 0) { throw new IllegalArgumentException("tableId can't be greater than MAX_TABLE_NUM or less than 0"); } long currStmp = timeGen(); if (currStmp < lastStmp) { throw new RuntimeException("Clock moved backwards. Refusing to generate id"); } if (currStmp == lastStmp) { //if条件里表示当前调用和上一次调用落在了相同毫秒内,只能通过第三部分,序列号自增来判断为唯一,所以+1. sequence = (sequence + 1) & MAX_SEQUENCE; //同一毫秒的序列数已经达到最大,只能等待下一个毫秒 if (sequence == 0L) { currStmp = getNextMill(); } } else { //不同毫秒内,序列号置为0 //执行到这个分支的前提是currTimestamp > lastTimestamp,说明本次调用跟上次调用对比,已经不再同一个毫秒内了,这个时候序号可以重新回置0了。 sequence = 0L; } lastStmp = currStmp; //就是用相对毫秒数、机器ID和自增序号拼接 return (currStmp - START_STMP) << TIMESTMP_LEFT //时间戳部分 | bizId << DATACENTER_LEFT //业务部分 | tableId << MACHINE_LEFT //数据库表部分 | sequence; //序列号部分 } //产生下一个ID public synchronized long nextId() { long currStmp = timeGen(); if (currStmp < lastStmp) { throw new RuntimeException("Clock moved backwards. Refusing to generate id"); } if (currStmp == lastStmp) { //if条件里表示当前调用和上一次调用落在了相同毫秒内,只能通过第三部分,序列号自增来判断为唯一,所以+1. sequence = (sequence + 1) & MAX_SEQUENCE; //同一毫秒的序列数已经达到最大,只能等待下一个毫秒 if (sequence == 0L) { currStmp = getNextMill(); } } else { //不同毫秒内,序列号置为0 //执行到这个分支的前提是currTimestamp > lastTimestamp,说明本次调用跟上次调用对比,已经不再同一个毫秒内了,这个时候序号可以重新回置0了。 sequence = 0L; } lastStmp = currStmp; //就是用相对毫秒数、机器ID和自增序号拼接 return (currStmp - START_STMP) << TIMESTMP_LEFT //时间戳部分 | bizId << DATACENTER_LEFT //业务部分 | tableId << MACHINE_LEFT //数据库表部分 | sequence; //序列号部分 } private long getNextMill() { long mill = timeGen(); while (mill <= lastStmp) { mill = timeGen(); } return mill; } private long timeGen() { return System.currentTimeMillis(); } /* // 测试 public static void main(String[] args) { SnowFlake snowFlow = new SnowFlake(1, 1); // for (int i = 0; i < 3; i++) { // System.out.println(snowFlow.nextId()); // } System.out.println(snowFlow.nextId()); }*/ }