参考:https://www.jianshu.com/p/331b872e9c8f

  1.建立一张存放的表

  

CREATE TABLE `sys_serial_number` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`module_name` varchar(50) DEFAULT NULL COMMENT '模块名称',
`module_code` varchar(50) DEFAULT NULL COMMENT '模块编码(唯一的)',
`config_templet` varchar(50) DEFAULT NULL COMMENT '订单前缀',
`max_serial` varchar(32) DEFAULT NULL COMMENT '存放当前序列号的值',
`pre_max_num` varchar(32) DEFAULT NULL COMMENT '预生成序列号存放到缓存的个数',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='序列自增长表';
package ch.service.sys;

import ch.common.util.CacheUtils;
import ch.dao.sys.SerialNumDao;
import ch.entity.sys.SystemSerialNumberEntity;
import ch.util.DateUtils;
import ch.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock; /**
* Description:
*
* @author cy
* @date 2019年05月07日 13:23
* version 1.0
*/
@Service
public class SerialNumberServiceImpl implements SerialNumService { @Autowired
private SerialNumDao serialNumDao; /** 日期格式 */
private String pattern = "yyyyMMddHHmmss"; /** 生成器锁 */
private final ReentrantLock lock = new ReentrantLock(); /** 流水号格式化器 */
private DecimalFormat format = new DecimalFormat(""); /** 预生成锁 */
private final ReentrantLock prepareLock = new ReentrantLock(); /** 最小值 */
private int min = ; /** 最大值 */
private long max = ; /** 已生成流水号(种子) */
private long seed = min; /** 预生成数量 */
private int prepare = ; /** 数据库存储的当前最大序列号 **/
long maxSerialInt = ; /** 当前序列号是否为个位数自增的模式 **/
private String isAutoIncrement = ""; /** 预生成流水号 */
HashMap<String, List<String>> prepareSerialNumberMap = new HashMap<>(); /**
* 查询单条序列号配置信息
* @param
* @return
*/
@Override
public SystemSerialNumberEntity find(SystemSerialNumberEntity entity) {
return null;
} /**
* 根据模块code生成预数量的序列号存放到Map中
* @param moduleCode 模块code
* @return
*/
@Transactional
public List<String> generatePrepareSerialNumbers(String moduleCode){
//临时List变量
List<String> resultList = new ArrayList<String>(prepare);
lock.lock();
// 查询数据库最大maxSerialInt
SystemSerialNumberEntity oneByCode = serialNumDao.findOneByCode(moduleCode);
if(oneByCode == null){
throw new RuntimeException("不存在模块code");
}
this.maxSerialInt = Long.valueOf(oneByCode.getMaxSerial());
this.prepare = Integer.valueOf(oneByCode.getPreMaxNum());
try {
for (int i = ; i < prepare; i++) {
maxSerialInt += ;
if(maxSerialInt > min && maxSerialInt < max){
seed = maxSerialInt;
}else {
// 如果动态数字长度大于模板中的长度 例:模板CF000 maxSerialInt 1000
seed = maxSerialInt = ;
}
// 动态数字生成拼接
String formatSerialNum = format.format(seed);
// 动态日期的生成拼接
if(StringUtils.isNotBlank(pattern)){
String date = DateUtils.getDate(pattern);
formatSerialNum = date + formatSerialNum;
}
if(StringUtils.isNotBlank(oneByCode.getConfigTemplet())){
formatSerialNum = oneByCode.getConfigTemplet() + formatSerialNum;
}
resultList.add(formatSerialNum);
}
//更新数据
oneByCode.setMaxSerial(maxSerialInt + "");
serialNumDao.update(oneByCode);
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
return resultList;
} /**
* 根据模块code生成序列号
* @param moduleCode 模块code
* @return 序列号
*/
@Override
@Transactional
public String generateSerialNumberByModelCode(String moduleCode) {
//预序列号加锁
prepareLock.lock();
try{
//判断内存中是否还有序列号
if(null != prepareSerialNumberMap.get(moduleCode) && prepareSerialNumberMap.get(moduleCode).size() > ){
//若有,返回第一个,并删除
return prepareSerialNumberMap.get(moduleCode).remove();
}
}catch (Exception e){
e.printStackTrace();
}finally {
//预序列号解锁
prepareLock.unlock();
}
List<String> resultList = generatePrepareSerialNumbers(moduleCode);
prepareLock.lock();
try {
prepareSerialNumberMap.put(moduleCode, resultList);
return prepareSerialNumberMap.get(moduleCode).remove();
} finally {
prepareLock.unlock();
}
} }

  

Java之流水号生成器实现的更多相关文章

  1. C# 流水号生成器开发

    前言 本文将使用一个Nuget公开的组件技术来实现一个流水号生成器,提供了一些简单的API,来方便的实现一个通用的流水号. 在visual studio 中的NuGet管理器中可以下载安装,也可以直接 ...

  2. Java设计模式:生成器模式

    问题的提出: 有些类很容易创建对象,直接调用其构造方法,例如Student student = new Student("1001","zhang",21); ...

  3. 结对编程1----基于java的四则运算生成器

    小组成员:王震(201421123054).王杰(201421123055) Coding地址:https://git.coding.net/a506504661/sssss.git 一.题目描述 我 ...

  4. Java设计模式-Builder生成器模式

    概念: 生成器模式也称之为建造者模式.生成器模式的意图在于将一个复杂的构建与其表示相分离,构建与产品分离. UML: Ibuild接口清晰地反映了创建产品Product的流程. 生成器模式涉及4个关键 ...

  5. 自定义java代码快捷生成器使用与问题解决

    对于很多的工作了有几年的开发人员来说,初期都是逐个单词语法的自己编写的.而一旦技术水平提高了到了一定的层次之后,在同时工作量的加大,要求我们必须加快提高工作效率.因此就可以利用必要的快捷开发手段和工具 ...

  6. java中生成流水号的一个例子(使用关系型数据库)

    在实际的开发中,可能会有根据一定的规则生成流水号的需求(比如根据根据公司编码和日期生成4位流水号)我们可以把公司和日期联合起来作为一个业务编码,把这个业务编码和序列的值存储到数据库中,每次需要生成流水 ...

  7. 【java】单实例下的 流水号【21位】

    单实例环境,不是分布式 需要流水号 /** * 流水号生成器 * * 年+天号+毫秒+随机数 * 2019+134+480+11位随机数 * 4+3+3+11 = 21位 * * * @author ...

  8. Spring Boot集成全局唯一ID生成器

    流水号生成器(全局唯一 ID生成器)是服务化系统的基础设施,其在保障系统的正确运行和高可用方面发挥着重要作用.而关于流水号生成算法首屈一指的当属 Snowflake雪花算法,然而 Snowflake本 ...

  9. Java二进制和位运算,这一万字准能喂饱你

    基础不牢,地动山摇.本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术栈.MyBatis.JVM.中间件等小而美的专栏供以免费学习.关注公众号[BAT的乌托 ...

随机推荐

  1. Struts2的各种标签库

    1 在JSP中使用taglib编译指令导入标签库 <%@ taglib prefix="s" uri="/struts-tags" %> ----- ...

  2. 【POJ 2478】 Farey Sequence

    [题目链接] 点击打开链接 [算法] 不难看出,ans = phi(2) + phi(3) + .... + phi(n-1) + phi(n) 线性筛筛出欧拉函数,预处理前缀和,即可 [代码] #i ...

  3. AutoIt:获取计算机已安装程序列表

    $file = FileOpen(@ScriptDir&"\RegInstalledItems.csv",1) if $file = -1 Then ConsoleWrit ...

  4. Bootstrap-CSS:辅助类

    ylbtech-Bootstrap-CSS:辅助类 1.返回顶部 1. Bootstrap 辅助类 本章将讨论 Bootstrap 中的一些可能会派上用场的辅助类. 文本 以下不同的类展示了不同的文本 ...

  5. vue微信公众号、H5微信支付

    1.H5微信支付 后台会返回一个URL,前端直接跳转就OK(需要你传给后台一个ip,必须保证在同一域名下) 使用window.location.href =res.data;进行页面跳转到支付界面(r ...

  6. servlet 3 文件上传

    1.up.jsp <%@ page language="java" pageEncoding="utf-8"%> <form action=& ...

  7. Linear Regression_最小二乘(LMS)

    %% Machine Learining----Linear Regression close all clear %%data load Year = linspace(,,); Price = [ ...

  8. Win10应用设计的那些事儿

    此文已由作者杨凯明授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 继Windows 10系统发布之后,很多Windows用户更新了系统.win10系统的发布,在以往的metr ...

  9. Mybatis 未设置主键映射报错;Cause: java.sql.SQLSyntaxErrorException: Unknown column 'system_id' in 'field list'

    使用MyBatis的时候,主键的字段建议绑定在Bean的属性上面, import javax.persistence.*; public class User { @Id @Column(name = ...

  10. 我的spring-boot开发环境

    我的spring-boot开发环境,目的方便我快速搭建开发环境,同时可以最佳实践.使用spring-boot 2.1.x. 代码地址:GitHub my-springboot-examples 目的是 ...