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的乌托 ...
随机推荐
- vue 随笔3
在整个vue项目中index.js只能有一个 ,创建vue组件实例的代码只能写在main.js中或者index.js中,别的文件中都是使用export default 常量 或者是方法
- javascript ==等于与===恒等于
==判断是否等于,只判断数值 ===代表恒等于,不仅判断数值,而且判断类型 var a=5; var b="5"; (a b 只是数值上相等,但是类型并不相等) a==b //tr ...
- Spring中AOP的两种代理方式(Java动态代理和CGLIB代理)
第一种代理即Java的动态代理方式上一篇已经分析,在这里不再介绍,现在我们先来了解下GCLIB代理是什么?它又是怎样实现的?和Java动态代理有什么区别? cglib(Code Generation ...
- k8s-基于canel的网络策略-十九
一.前提 上一节学习了flannel,但是我们应该了解flannel只能提供网络通讯,而不能提供网络策略.因此,我们本节学习canal,让它来提供网络策略,来配合flannel使用. canal是ca ...
- C++经典面试题库 附带参考答案
1. 面向对象的程序设计思想是什么? 答:把数据结构和对数据结构进行操作的方法封装形成一个个的对象. 2. 什么是类? 答:把一些具有共性的对象归类后形成一个集合,也就是所谓的类. 3. ...
- [问题][已解决] 并发场景下 "mysql: too many connections" 原因
问题出现是这样的,用node写爬虫, 之前每条数据都是await插入,并且是阻塞的,后来改成了非阻塞,可以并行插入操作,结果一直找不到原因. 后来在日志中找到了 too many connection ...
- C++面向对象程序设计举例
[例8.1]最简单的例子. #include <iostream> using namespace std; class Time //定义Time类 { public : //数据成员为 ...
- C++11六大函数(构造函数,移动构造函数,移动赋值操作符,复制构造函数,赋值操作符,析构函数)
在C++中,有三大函数复制控制(复制构造函数,赋值操作符,析构函数),而在C++11中,加入了移动构造函数,移动赋值操作符.我就斗胆将他们命名为六大函数好了. 一.构造函数 c++primer中说过: ...
- [BZOJ5120]无限之环
Description 曾经有一款流行的游戏,叫做InfinityLoop,先来简单的介绍一下这个游戏: 游戏在一个n×m的网格状棋盘上进行,其中有些小方格中会有水管,水管可能在方格某些方向的边界的中 ...
- jmeter(十九)调试工具Debug Sampler
一.Debug Sampler介绍: 使用Jmeter开发脚本时,难免需要调试,这时可以使用Jmeter的Debug Sampler,它有三个选项:JMeter properties,JMeter v ...