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的乌托 ...
随机推荐
- IOS中的沙盒机制
IOS中的沙盒机制(SandBox)是一种安全体系,它规定了应用程序只能在为该应用创建的文件夹内读取文件,不可以访问其他地方的内容.所有的非代码文件都保存在这个地方,比如图片.声音.属性列表和文本文件 ...
- 「网络流24题」「LuoguP4015」 运输问题
Description W 公司有 m 个仓库和 n 个零售商店.第 i 个仓库有 ai 个单位的货物:第 j 个零售商店需要 bj 个单位的货物. 货物供需平衡,即 ∑ai=∑bj . 从第 i ...
- http监听工具Fildder
空间管理您的位置: 51Testing软件测试网 » 雨洒泪 » 日志 中国龙,中国风,中国会变得更加强大! 力量越大,责任越大! 人的一生,会面临很多选择,但决定一个人一生的,往往就是最关键那么的一 ...
- Com组件介绍
COM组件简介 面向对象的思想难以适应这种分布式软件模型,于是组件化程序设计思想得到了迅速的发展. 按照组件化的程序设计的思想,复杂的应用程序被设计成一些小的,功能单一的组件模块,这些组件模块可以运行 ...
- 基于 Laravel 5 构建的、支持模块化和多语言的 CMS —— AsgardCMS
1.简介 AsgardCMS 是基于 Laravel 5 构建的.支持模块化和多语言的CMS. 官网:https://asgardcms.com/ Github:https://github.com/ ...
- Bootstrap-CL:下拉菜单
ylbtech-Bootstrap-CL:下拉菜单 1.返回顶部 1. Bootstrap 下拉菜单(Dropdowns) 本章将重点介绍 Bootstrap 下拉菜单.下拉菜单是可切换的,是以列表格 ...
- hdoj5003【wa水】
蜜汁wa,蜜汁wa,少了个\n------ #include<bits/stdc++.h> using namespace std; typedef long long LL; typed ...
- sublime text3 注册码
—– BEGIN LICENSE —– TwitterInc 200 User License EA7E-890007 1D77F72E 390CDD93 4DCBA022 FAF60790 61AA ...
- bzoj 1022: [SHOI2008]小约翰的游戏John【anti-nim】
如果全是1,那么n是奇数先手必败 否则,xor和为0先手必败 证明见 https://www.cnblogs.com/Wolfycz/p/8430991.html #include<iostre ...
- php 中的引用(&)与foreach结合后的一个注意点
关于php中引用的概念及foreach循环的的应用就不多说了,php文档已经说的很明白了.直接上一段代码: <?php $arr = array(1,2, 3); foreach($arr as ...