锁定老帖子 主题:一个循环流水号实现,求评
精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (4)
|
|
---|---|
作者 | 正文 |
发表时间:2011-09-19
最后修改:2011-09-19
1.要可以设初始值
2.补0这种事交给Format 去作 '0' The result will be zero-padded 又好懂又没bug 3.现在spring这么流行,你用static这种方式有点土了。 |
|
返回顶楼 | |
发表时间:2011-09-19
zuzong 写道 Crusader 写道 AnotherTomorrow 写道 hareamao 写道 方法的头一段可以改成:
int n = ++serialNumber; serialNumber %= 999999; 另外,你的程序不考虑系统重启的可能性么? 小小纠正一下,按楼主要求,应该是 int n = serialNumber = serialNumber%999999 + 1; 应该是可以不同步整个方法的吧,n属于局部变量,只要同步serialNumber部分就可以了。 有问题吧,这样一直加下去,不考虑int溢出吗? 整个操作过程 check - save - get 应该封装为原子操作,同时可以考虑使用jdk的原子变量类来简化过程 因为到了999999就设为0,重新计数,系统重启没考虑了,小弟又修改了下,恳请各位大哥指导啊~ public class SerialNumber { private static SerialNumber instance = new SerialNumber(); public static SerialNumber getInstance(){ return SerialNumber.instance; } private SystemParamDAO systemParamDAO; /** * 流水号 */ private static volatile int serialNumber = 0; /** * 读取数据库中初始,或中断时记录的流水号 */ public void initSerialNumber() { SerialNumber.serialNumber = Integer.parseInt(this.systemParamDAO.search("serial_number")); } /** * 生成流水号 * 从1 - 999999,不足六位,从右往左补0 * @return */ public synchronized String generateSerialNumber(){ int n = serialNumber = ++serialNumber; if(n == (999999 + 1)){ serialNumber = n = 1; } SerialNumber.instance.systemParamDAO.updateBySerialNumber(n); StringBuffer strbu = new StringBuffer(6); strbu.append(n); for(int i=0, length=6-strbu.length(); i<length; i++){ strbu.insert(0, 0); } return strbu.toString(); } public void setSystemParamDAO(SystemParamDAO systemParamDAO) { this.systemParamDAO = systemParamDAO; } } 这个貌似不是单利吧,没声明private的构造方法 |
|
返回顶楼 | |
发表时间:2011-09-19
晕,刚才写了半天回复,一提交,居然不见了
|
|
返回顶楼 | |
发表时间:2011-09-19
最后修改:2011-09-19
感谢大家的回复,
我用的spring,systemParamDAO是注进来的,initSerialNumber方法也是在spring配置文件里设置的init-method 调用方是个helper类,原本那里是没有数据库操作的,但流水号又需要保存。。。想来想去,干脆把systemParamDAO当参数传进去吧,总归是要注入的,注入systemParamDAO,总比注入我这个流水号的好些 synchronized 是为了保证++serialNumber的计算 改成了这样 public class SerialNumber { private SystemParamDAO systemParamDAO; /** * 流水号 */ private static volatile int serialNumber = 0; /** * 读取数据库中初始,或中断时记录的流水号 */ public void initSerialNumber() { SerialNumber.serialNumber = Integer.parseInt(this.systemParamDAO.search("serial_number")); } /** * 生成流水号 * 从1 - 999999,不足六位,从右往左补0 * @return */ public synchronized static String generateSerialNumber(SystemParamDAO systemParamDAO){ int n = serialNumber = ++serialNumber; if(n == (999999 + 1)){ serialNumber = n = 1; } systemParamDAO.updateBySerialNumber(n); StringBuilder strbu = new StringBuilder(6); strbu.append(n); for(int i=0, length=6-strbu.length(); i<length; i++){ strbu.insert(0, 0); } return strbu.toString(); } public void setSystemParamDAO(SystemParamDAO systemParamDAO) { this.systemParamDAO = systemParamDAO; } } |
|
返回顶楼 | |
发表时间:2011-09-19
多线程下,试试AtomicLong呢...
|
|
返回顶楼 | |
发表时间:2011-09-19
估计用的是MYSQL......
|
|
返回顶楼 | |
发表时间:2011-09-19
调用参数里面还得传一个dao,这有点怪异吧
getNextSerialNumber不一定非得是static的 可以每次取下一个序列的时候都检查一下有没有初始化过,如果没有初始化,那么先从数据库读取数据进行初始化 如果已经初始化了,那么直接返回(内存中保存的数据+1)%LIMIT private static volatile boolean INITED = false; private static volatile int SN = 0; private void init(){ SN = xxxDao.xx(); // 从数据库加载最后一次持久化的值 INITED = true; } public synchronized String getNextSerialNumber(){ if(!INITED) init(); SN = (SN + 1) % LIMIT; // TODO: 更新数据库 return String.format("%06d", SN); } |
|
返回顶楼 | |
发表时间:2011-09-19
最后修改:2011-09-19
weiqiang.yang 写道 调用参数里面还得传一个dao,这有点怪异吧
getNextSerialNumber不一定非得是static的 可以每次取下一个序列的时候都检查一下有没有初始化过,如果没有初始化,那么先从数据库读取数据进行初始化 如果已经初始化了,那么直接返回(内存中保存的数据+1)%LIMIT private static volatile boolean INITED = false; private static volatile int SN = 0; private void init(){ SN = xxxDao.xx(); // 从数据库加载最后一次持久化的值 INITED = true; } public synchronized String getNextSerialNumber(){ if(!INITED) init(); SN = (SN + 1) % LIMIT; // TODO: 更新数据库 return String.format("%06d", SN); } 如果再使用 java.util.concurrent.atomic.AtomicLong long old = SN.longvalue long new = (old+1)%LIMIT; SN.weakCompareAndSet(old,new); 来作SN 就更加理想了, 去掉同步块大大增加多线程访问次数 最主要的是只看到业务逻辑 没看到丑陋的java底层代码 PS:为了好测试,可以把 if(!INITED) init(); 放到spring的 initmethod里面去。 |
|
返回顶楼 | |
发表时间:2011-09-19
最好从100000 开始,
|
|
返回顶楼 | |
发表时间:2011-09-19
这系统重启不就恢复了嘛
|
|
返回顶楼 | |