美文网首页
UUID生成方案

UUID生成方案

作者: 大华夏 | 来源:发表于2019-04-05 08:54 被阅读0次

    UUID组成部分

    1+分片标识符+年月日+递增数字
    其中递增数字,长度不够前面补0

    实现

    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Date;
    import java.util.concurrent.atomic.AtomicLong;
    
    public class UUIDGenerator {
        // 分片号,占4位
        private static String slotId;
        // 是否调用init()方法进行初始化
        private static boolean inited = false;
    
        private static int date;
    
        private static AtomicLong incre = new AtomicLong(1);
        private static final String DataFormat = "yyMMdd";
        private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>();
    
        private static DateFormat getDateFormat() {
            DateFormat df = threadLocal.get();
            if (df == null) {
                df = new SimpleDateFormat(DataFormat);
                threadLocal.set(df);
            }
            return df;
        }
        /**
         * 按指定格式对Date所持有的时间进行格式化
         * @param date
         * @return
         */
        private static int format(Date date) {
            return Integer.valueOf(getDateFormat().format(date));
        }
        /**
         * 指定时间戳所在日期的0点时间戳
         * @param millis
         * @return
         */
        private static long zeroTime(long millis) {
            Calendar calendar = Calendar.getInstance();
            // TimeZone curTimeZone = TimeZone.getTimeZone("GMT+8");
            // Calendar calendar = Calendar.getInstance(curTimeZone);
    
            calendar.setTimeInMillis(millis);
            calendar.set(Calendar.HOUR_OF_DAY, 0);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
            calendar.set(Calendar.MILLISECOND, 0);
            return calendar.getTimeInMillis();
        }
    
        /**
         * 在使用前调初始化
         * 
         * @param slotId
         */
        public static void init(int slotId) {
            if (inited) {
                return;
            }
            if (slotId >= 1000) {
                throw new RuntimeException("Slot ID must be smaller than 10000");
            }
            UUIDGenerator.slotId = String.format("%03d", slotId);
            inited = true;
        }
        /**
         * 生成UUID
         * @return
         */
        public static long generate() {
            if (!inited) {
                throw new RuntimeException("The init() method must be called first");
            }
            int currDate = format(new Date());
    
            if (currDate != date) {
                synchronized (UUIDGenerator.class) {
                    if (currDate != date) {
                        //自增偏移量,初始值设置为当日的秒数,防止因重启或其他原因造成生成的ID重复
                        long offset = 1+(System.currentTimeMillis() - zeroTime(System.currentTimeMillis()))/1000;
                        System.out.println("offset: "+offset);
                        incre.set(offset);
                        date = currDate;
                    }
                }
            }
            String uuid = String.format("1%s%d%09d", slotId, date, incre.getAndIncrement());
            return Long.valueOf(uuid);
        }
    
        public static void main(String[] args) throws InterruptedException {
            UUIDGenerator.init(5);
            int jmax = 1000;
            CountDownLatch countDownLatch = new CountDownLatch(10);
            HashSet<Long> uuids = new HashSet<>();
            for (int i = 0; i < 10; i++) {
                new Thread(() -> {
                    for (int j = 0; j < jmax; j++) {
                        long uuid = UUIDGenerator.generate();
                        System.out.println(uuid);
                        uuids.add(uuid);
                    }
                    countDownLatch.countDown();
                }).start();
            }
            countDownLatch.await();
            if(uuids.size() != jmax*10) {
                System.out.println("UUID generate error ...... !!!");
            }else {
                System.out.println("UUID generate success!!!");
            }
        }
    }
    

    总结

    每日可保存上亿的UUID生成,足够项目使用。

    相关文章

      网友评论

          本文标题:UUID生成方案

          本文链接:https://www.haomeiwen.com/subject/bskhiqtx.html