zoukankan      html  css  js  c++  java
  • 生成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());
            }
    
        }
    }
  • 相关阅读:
    【转】React Native 关于箭头函数、普通函数与点击事件的调用
    【转】React Native Config.h not found ( glog-0.3.4 )
    微软必应Bing搜索引擎这几天无法访问!
    Beyond Compare 4 提示错误“这个授权密钥已被吊销”的解决办法
    flock
    Getting.Started.with.Unity.2018.3rd.Edition
    Joe Hocking
    Unity 2018 By Example 2nd Edition
    Unity 2017 Game Optimization 新版
    Why is it called “armature” instead of “skeleton”? or perhaps “rig”?
  • 原文地址:https://www.cnblogs.com/dongma/p/14873255.html
Copyright © 2011-2022 走看看