• java三种生成ID算法(测试运行时间)


    单线程:

    10000次测试生成ID

     RandomUtilIDWorkerNoCenter
    第一次 0.187s 0.036s 0.324s
    第二次 0.121s 0.05s 0.305s
    第三次 0.131s 0.036s 0.283s

    100000测试生成ID

     RandomUtilIDWorkerNoCenter
    第一次 0.678s 0.191s 0.922s
    第二次 0.678s 0.201s 0.846s
    第三次 0.684s 0.197s 0.932s

    1000000测试生成ID

     RandomUtilIDWorkerNoCenter
    第一次 4.442s 1.933s 4.387s
    第二次 4.316s 1.864s 4.571s
    第三次 4.25s 1.782s 4.499s

    10000000测试生成ID

     RandomUtilIDWorkerNoCenter
    第一次 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");
        }
    
    }
    View Code

    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");
        }
    
    }
    View Code

    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");
        }
    
    
    }
    View Code
    生成算法是从网上找的,非本人纯手撸!
    在此感谢
     
  • 相关阅读:
    struts2 spring3 整合
    SilverLight 银光 基础.net 跨网页,桌面软件体验更好,但是要这个插件
    struts 理解 action
    vb 坐标点击
    错误struts2 json There is no Action mapped for namespace
    struts 与 jquery 整合
    springmvc jquery 界面没回应
    css 相关学习
    spring + ehcache 配置
    jquery json 结合
  • 原文地址:https://www.cnblogs.com/zhunong/p/14012175.html
Copyright © 2020-2023  润新知