UUID生成方案

2019-04-05  本文已影响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生成,足够项目使用。

上一篇下一篇

猜你喜欢

热点阅读