Java之流水号生成器实现
参考: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之流水号生成器实现的更多相关文章
- C# 流水号生成器开发
前言 本文将使用一个Nuget公开的组件技术来实现一个流水号生成器,提供了一些简单的API,来方便的实现一个通用的流水号. 在visual studio 中的NuGet管理器中可以下载安装,也可以直接 ...
- Java设计模式:生成器模式
问题的提出: 有些类很容易创建对象,直接调用其构造方法,例如Student student = new Student("1001","zhang",21); ...
- 结对编程1----基于java的四则运算生成器
小组成员:王震(201421123054).王杰(201421123055) Coding地址:https://git.coding.net/a506504661/sssss.git 一.题目描述 我 ...
- Java设计模式-Builder生成器模式
概念: 生成器模式也称之为建造者模式.生成器模式的意图在于将一个复杂的构建与其表示相分离,构建与产品分离. UML: Ibuild接口清晰地反映了创建产品Product的流程. 生成器模式涉及4个关键 ...
- 自定义java代码快捷生成器使用与问题解决
对于很多的工作了有几年的开发人员来说,初期都是逐个单词语法的自己编写的.而一旦技术水平提高了到了一定的层次之后,在同时工作量的加大,要求我们必须加快提高工作效率.因此就可以利用必要的快捷开发手段和工具 ...
- java中生成流水号的一个例子(使用关系型数据库)
在实际的开发中,可能会有根据一定的规则生成流水号的需求(比如根据根据公司编码和日期生成4位流水号)我们可以把公司和日期联合起来作为一个业务编码,把这个业务编码和序列的值存储到数据库中,每次需要生成流水 ...
- 【java】单实例下的 流水号【21位】
单实例环境,不是分布式 需要流水号 /** * 流水号生成器 * * 年+天号+毫秒+随机数 * 2019+134+480+11位随机数 * 4+3+3+11 = 21位 * * * @author ...
- Spring Boot集成全局唯一ID生成器
流水号生成器(全局唯一 ID生成器)是服务化系统的基础设施,其在保障系统的正确运行和高可用方面发挥着重要作用.而关于流水号生成算法首屈一指的当属 Snowflake雪花算法,然而 Snowflake本 ...
- Java二进制和位运算,这一万字准能喂饱你
基础不牢,地动山摇.本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术栈.MyBatis.JVM.中间件等小而美的专栏供以免费学习.关注公众号[BAT的乌托 ...
随机推荐
- 通用异步 Windows Socket TCP 客户端组件的设计与实现
编写 Windows Socket TCP 客户端其实并不困难,Windows 提供了6种 I/O 通信模型供大家选择.但本座看过很多客户端程序都把 Socket 通信和业务逻辑混在一起,剪不断理还乱 ...
- HAOI2012高速公路——子区间计算
题目:https://www.luogu.org/problemnew/show/P2221 似乎按点来算贡献很方便,但我抱住一篇没有这样的题解磕了两天... 以下转载: 题意:维护一段数列 支持区间 ...
- spark运行原理
一.Spark专业术语定义 二. Spark的任务提交机制 一.Spark专业术语定义 从以下十五个方面描述spark概念. 1 application: spark应用程序 2 Driver:驱 ...
- bzoj1038&&500AC!
序列dp 先开始想了一个类似区间dp的东西...少了一维 然后发现似乎不太对,因为女生的最大差和男生的最大差并不相等 dp[i][j][x][y]表示当前有i个人,j个男生,男生和女生的后缀最大差是x ...
- 【旧文章搬运】Windbg+Vmware驱动调试入门(四)---VirtualKD内核调试加速工具
原文发表于百度空间,2009-01-09========================================================================== 今天又想起 ...
- Win7系统打开服务管理界面的几种方法汇总
转自:https://www.jb51.net/os/windows/318465.html Win7服务管理包含了计算机操作系统和应用程序提供的所有服务,但是这么多服务并非总是用户所需的.比如打印机 ...
- 斯坦福CS231n—深度学习与计算机视觉----学习笔记 课时24&&25
课时24 深度学习开源库使用介绍(上) Caffe 被用于重新实现AlexNet,然后用AlexNet的特征来解决其他事情 用C++书写的,可以去GitHub上面读取源代码 主要四个类: Blob可以 ...
- python __builtins__ bytearray类 (7)
7.'bytearray', 返回一个新字节数组.这个数组里的元素是可变的,并且每个元素的值范围: 0 <= x < 256. class bytearray(object) | byte ...
- bzoj 4871: [Shoi2017]摧毁“树状图”【树形dp】
做不来--参考https://www.cnblogs.com/ezyzy/p/6784872.html #include<iostream> #include<cstdio> ...
- Rsync 实现远程同步
介绍 rsync命令是一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间的文件.rsync使用所谓的“rsync算法”来使本地和远程两个主机之间的文件达到同步,这个算法只传送两个文件的不同部 ...