• 生成4位随机数


    本来是用随机算法的,但是会有重复,花了点时间研究了下,发现雪花算法好似不会重复,

    代码如下:

    package com.excel.test;
    
    import java.util.concurrent.atomic.AtomicInteger;
    
    public class MinuteCounter {
        private static final int MASK = 0x7FFFFFFF;
        private final AtomicInteger atom;
        
        public MinuteCounter() {
            atom = new AtomicInteger(0);
        }
        
        public final int incrementAndGet() {
            return atom.incrementAndGet() & MASK;
        }
        
        public int get() {
            return atom.get() & MASK;
        }
        
        public void set(int newValue) {
            atom.set(newValue & MASK);
        }
    }
    package com.excel.test;
    
    /**
     * 此方式只适用于一个单体应用,不适合分布式系统
     *
     *  将产生的Id类型更改为Integer 32bit <br>
     *  把时间戳的单位改为分钟,使用25个比特的时间戳(分钟) <br>
     *  去掉机器ID和数据中心ID <br>
     *  7个比特作为自增值,即2的7次方等于128。
     *
     */
    public class SnowflakeIdWorker3rd {
        /** 开始时间戳 (2019-01-01) */
        private final int twepoch = 25771200;// 1546272000000L/1000/60;
    
        /** 序列在id中占的位数 */
        private final long sequenceBits = 7L;
    
        /** 时间截向左移7位 */
        private final long timestampLeftShift = sequenceBits;
    
        /** 生成序列的掩码,这里为127 */
        private final int sequenceMask = -1 ^ (-1 << sequenceBits);
    
        /** 分钟内序列(0~127) */
        private int sequence = 0;
        private int laterSequence = 0;
    
        /** 上次生成ID的时间戳 */
        private int lastTimestamp = -1;
    
        private final MinuteCounter counter = new MinuteCounter();
        
        /** 预支时间标志位 */
        boolean isAdvance = false;
    
        // ==============================Constructors=====================================
        public SnowflakeIdWorker3rd() {
    
        }
    
        // ==============================Methods==========================================
        /**
         * 获得下一个ID (该方法是线程安全的)
         * 
         * @return SnowflakeId
         */
        public synchronized int nextId() {
            
            
            int timestamp = timeGen();
            // 如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
            if (timestamp < lastTimestamp) {
                throw new RuntimeException(String.format(
                        "Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
            }
            
            if(timestamp > counter.get()) {
                counter.set(timestamp);
                isAdvance = false;
            }
    
            // 如果是同一时间生成的,则进行分钟内序列
            if (lastTimestamp == timestamp || isAdvance) {
                if(!isAdvance) {
                    sequence = (sequence + 1) & sequenceMask;
                }
    
                // 分钟内自增列溢出
                if (sequence == 0) {
                    // 预支下一个分钟,获得新的时间戳
                    isAdvance = true;
                    int laterTimestamp = counter.get();
                    if (laterSequence == 0) {
                        laterTimestamp = counter.incrementAndGet();
                    }
    
                    int nextId = ((laterTimestamp - twepoch) << timestampLeftShift) //
                            | laterSequence;
                    laterSequence = (laterSequence + 1) & sequenceMask;
                    return nextId;
                }
            }
            // 时间戳改变,分钟内序列重置
            else {
                sequence = 0;
                laterSequence = 0;
            }
    
            // 上次生成ID的时间截
            lastTimestamp = timestamp;
    
            // 移位并通过或运算拼到一起组成32位的ID
            return ((timestamp - twepoch) << timestampLeftShift) //
                    | sequence;
        }
    
        /**
         * 返回以分钟为单位的当前时间
         * 
         * @return 当前时间(分钟)
         */
        protected int timeGen() {
            String timestamp = String.valueOf(System.currentTimeMillis() / 1000 / 60);
            return Integer.valueOf(timestamp);
        }
    
    }

      

    测试类

    package com.excel.test;
    
    import java.util.HashSet;
    import java.util.Set;
    
    public class Main {
        public static void main(String[] args) throws InterruptedException {
            SnowflakeIdWorker3rd worker3rd = new SnowflakeIdWorker3rd();
    
            Set<Integer> set = new HashSet<>();
    
            for (int j = 0; j < 50; j++) {
                for (int i = 0; i < 100; i++) {
                    int l = worker3rd.nextId();//% 10000;
    
                    Thread.sleep(10);
                    set.add(l);
                }
                System.out.println(set.size());
            }
    
        }
    }
  • 相关阅读:
    [六、常用控件]1UIButton控件的使用
    [五、视图控制器]18在故事板中设置初始视图控制器
    [五、视图控制器]13视图控制器和滚动视图
    [五、视图控制器]16导航视图控制器的入栈和出栈
    [五、视图控制器]17自定义导航控制器的导航按钮
    [五、视图控制器]12UITapGestureRecognizer手势之双击
    [五、视图控制器]15导航视图控制器的使用
    [五、视图控制器]19在故事板中使用标签和按钮控件
    [五、视图控制器]11UITapGestureRecognizer手势之长按
    [六、常用控件]4UILabel自定义文字样式
  • 原文地址:https://www.cnblogs.com/dongma/p/14873255.html
Copyright © 2020-2023  润新知