ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

ID生成,主键生成工具

2021-09-22 12:00:38  阅读:157  来源: 互联网

标签:String final private 主键 int static PAD 生成 ID


package com.iwhalecloud.basetool.asyncimpexpbase.common;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.security.SecureRandom;
import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * KeyGenerator 主键生成工具
 *
 * @author huang.wu@iwhalecloud.com
 * @date 2021/7/11
 */
public class KeyGenerator {

    public static final int INCREMENR_LIMIT = 89999;
    public static final int INCREMENT_INITIA = 10000;
    public static final int DATE_MILL_FACTOR = 1000;

    private KeyGenerator() {
    }


    /**
     * 时间戳格式
     */
    private static final String DATE_FORMAT = "yyyyMMddHHmmss";
    /**
     * 随机数位数
     */
    private static final int RANDOM_BOUND = 9000;
    /**
     * 时间填充位数
     */
    private static final int SEQ_TIME_PAD_SIZE = 4;
    /**
     * 随机数填充位数
     */
    private static final int RANDOM_PAD_SIZE = 1000;
    /**
     * 填充数
     */
    private static final String PAD_CHAR = "0";


    /**
     * 防止重复的自增
     */
    private static AtomicInteger increment = new AtomicInteger(INCREMENT_INITIA);

    private static SecureRandom random = new SecureRandom();

    /**
     * 表主键生成
     *
     * @return
     */
    public static String generateId() {
        Date now = new Date();

        String dateStr = DateFormatUtils.format(now, DATE_FORMAT);

        String seqFromTime = StringUtils.leftPad(Long.toString(now.getTime() % DATE_MILL_FACTOR), SEQ_TIME_PAD_SIZE, PAD_CHAR);


        String randomStr = String.valueOf(random.nextInt(RANDOM_BOUND) + RANDOM_PAD_SIZE);


        int inc = increment.getAndIncrement();
        //因为无锁,如果有多个线程同时执行这个方法调用,最大可能会被加到90099,也就是说以上算法如果有超过10000个线程并发调用会有问题
        //此情况下可以考虑扩大自增范围
        //同时如果并发太高,1ms内创建的订单数超过79998,即qps超过79999万时也有一亿分之一的概率重复
        if (increment.get() >= INCREMENR_LIMIT) {
            increment.set(INCREMENT_INITIA);
        }

        return dateStr + seqFromTime + inc + randomStr;

    }

    /**
     * 表主键生成,可指定前缀
     *
     * @return
     */
    public static String generateId(String prefix) {
        Date now = new Date();

        String dateStr = DateFormatUtils.format(now, DATE_FORMAT);

        String seqFromTime = StringUtils.leftPad(Long.toString(now.getTime() % DATE_MILL_FACTOR), SEQ_TIME_PAD_SIZE, PAD_CHAR);


        String randomStr = String.valueOf(random.nextInt(RANDOM_BOUND) + RANDOM_PAD_SIZE);


        int inc = increment.getAndIncrement();
        //因为无锁,如果有100个线程同时执行这个方法调用,最大可能会被加到90099,也就是说以上算法如果有超过10000个线程并发调用会有问题
        //此情况下可以考虑扩大自增范围
        //同时如果并发太高,1ms内创建的订单数超过79998,即qps超过7999万时也有一亿分之一的概率重复
        if (increment.get() >= INCREMENR_LIMIT) {
            increment.set(INCREMENT_INITIA);
        }

        return (prefix != null && prefix.length() > 0 ? prefix : "") + dateStr + seqFromTime + inc + randomStr;

    }

    public static void main(String[] args) {
        System.out.println(generateId());
        System.out.println(generateId().length());

        System.out.println(generateId("110"));
        System.out.println(generateId("110").length());
    }


}

标签:String,final,private,主键,int,static,PAD,生成,ID
来源: https://blog.csdn.net/Connie1451/article/details/120412502

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有