java如何根据时间戳生成有序ID

 更新时间:2024年04月15日 10:01:57   作者:紫金丨小飞侠  
这篇文章主要介绍了java如何根据时间戳生成有序ID问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

引言

我们常用的主键有这么几种

1. 数据库自增主键,比如mysql的autoincrement,这种插入快,但是识别度不高

2. uuid 这个号称是全球唯一的,但是无序,没有实际意义,只能保证唯一

3. 时间戳,这种在分布式的场景下就需要考虑更多种情况

4. 雪花算法 snow flake ,分布式全局唯一主键,很牛,但是我觉得用起来也挺麻烦哈哈哈

所以在并发情况没那么大的时候用一个工具类搞定,我就是这么懒

工具类

@Slf4j
public class NumUtil {

    private static long tmpID = 0;
    private static final long LOCK_TIME = 1;
    private static final long INCREASE_STEP = 1;
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmssSSS");
    private static final Lock LOCK = new ReentrantLock();


    public static long nextPkId() throws InterruptedException {
        //当前:(年、月、日、时、分、秒、毫秒)
        long timeCount;
        if (LOCK.tryLock(LOCK_TIME, TimeUnit.SECONDS)) {
            timeCount = Long.parseLong(sdf.format(new Date()));
            try {
                if (tmpID < timeCount) {
                    tmpID = timeCount;
                } else {
                    tmpID += INCREASE_STEP;
                    timeCount = tmpID;
                }
                return timeCount;
            } finally {
                LOCK.unlock();
            }
        } else {
            log.error("lock failed");
            return nextPkId();

        }
    }
}

贴上代码,这里用了当前时间,精确到毫秒级,如果有需要的话可以在实例化timeCount的时候乘以10或者100 1000之类的,这个看大家,然后加上锁,防止线程不安全的情况,加锁失败的时候递归,再来一次。

也可以使用synchronized做成同步方法,当中的区别下次再讨论。

有评论说宕机会导致tmpID归0导致已经使用过超出当前时间的ID,所以持久化这个tmpID也是可以的。

但这也就是在并发没那么高的情况下才使用这种方法,一般并发场景下还是分布式锁+推特的雪花算法解决。

测试

public static void numTest() {
        ExecutorService executorService = Executors.newCachedThreadPool();
        int n = 10000;
        List<Long> list = new ArrayList<>();
        CountDownLatch latch = new CountDownLatch(n);
        for (int i = 0; i < n; i++) {
            executorService.execute(() -> {
                //执行业务请求
                try {
                    list.add(NumUtil.nextPkId());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                latch.countDown();
            });
        }
        try {
            // 一定记得加上timeout时间,防止阻塞主线程
            latch.await(3000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            log.error(e.getMessage());
        }
        //4.等待所有子任务完成,组装内容
        while (list.size() < n) {
            log.info("集合长度 >>> {}",list.size());
        }
        //5.关闭线程池
        executorService.shutdown();

        for (Long aLong : list) {
            System.out.println(aLong);
        }
    }

然后噼里啪啦打印了一万个ID,没有重复的,一秒以内生成

结论

当然这种只是为了单体或者是并发没有高到那么离谱的场景下使用,效率我觉得还不错,分布式的场景下可能需要用到redis的自增来计数以达到数据安全的效果

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家

相关文章

  • idea项目的左侧目录没了如何设置

    idea项目的左侧目录没了如何设置

    这篇文章主要介绍了idea项目的左侧目录没了如何设置的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • springboot更新配置Swagger3的一些小技巧

    springboot更新配置Swagger3的一些小技巧

    今天给大家分享springboot更新配置Swagger3的方法,大家需要注意Swagger3版本需要引入依赖,具体示例代码参考下本文
    2021-07-07
  • Spring Boot实现分布式系统中的服务发现和注册(最新推荐)

    Spring Boot实现分布式系统中的服务发现和注册(最新推荐)

    在本文中,我们深入探讨了Spring Boot如何实现分布式系统中的服务发现和注册,我们使用Eureka作为服务注册中心,Ribbon作为负载均衡器,Hystrix作为熔断器,成功地实现了服务发现、服务注册、负载均衡和服务熔断等功能,需要的朋友参考下吧
    2023-06-06
  • Jmeter BeanShell 内置变量vars、props、prev的使用详解

    Jmeter BeanShell 内置变量vars、props、prev的使用详解

    这篇文章主要介绍了Jmeter BeanShell 内置变量vars、props、prev的使用 ,文中给大家介绍了Jmeter中关于BeanShell的相关知识,结合实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2022-10-10
  • Java中操作超大数的方法

    Java中操作超大数的方法

    本篇文章是小编在网上整理的关于java操作超大数的方法以及解决思路,有兴趣的朋友参考学习下。
    2018-06-06
  • Java OpenCV利用KNN算法实现图像背景移除

    Java OpenCV利用KNN算法实现图像背景移除

    这篇文章主要为大家介绍了Java OpenCV利用K最邻近(KNN,K-NearestNeighbor)分类算法实现图像背景移除的示例代码,需要的可以参考一下
    2022-01-01
  • 区块链java代码实现

    区块链java代码实现

    这篇文章主要为大家详细介绍了区块链java代码实现,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • spring boot 全局异常处理方法汇总

    spring boot 全局异常处理方法汇总

    这篇文章主要介绍了spring boot 全局异常处理方法汇总,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • mybatis 映射文件中if标签判断字符串相等的两种方式

    mybatis 映射文件中if标签判断字符串相等的两种方式

    这篇文章主要介绍了mybatis 映射文件中if标签判断字符串相等的方式,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-06-06
  • mybatis中的setting配置详解

    mybatis中的setting配置详解

    这篇文章主要给大家介绍了关于mybatis中setting配置的相关资料,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2017-06-06

最新评论