论坛首页 Java企业应用论坛

一个循环流水号实现,求评

浏览 13180 次
精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (4)
作者 正文
   发表时间:2011-09-17   最后修改:2011-09-17
给了个需求,要求做一个1 - 999999的循环的流水号生成方法,小弟没做个类似的东西,摸索着写了个,特来求评,还望赐教
	/**
	 * 流水号
	 */
	private static volatile int serialNumber = 0;
	/**
	 * 生成流水号
	 * 从1 - 999999,不足六位,从右往左补0
	 * @return
	 */
	public static synchronized String generateSerialNumber(){
		int n = serialNumber = ++serialNumber;
		if(n == (999999 + 1)){
			serialNumber = n = 1;
		}
		
		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();
	}

生成的数字测过,没问题,就是不知道这么写在多线程时靠不靠谱,当并发多大的时候,会出问题吗?

   发表时间:2011-09-18  
方法的头一段可以改成:

        int n = ++serialNumber;
        serialNumber %= 999999;


另外,你的程序不考虑系统重启的可能性么?
0 请登录后投票
   发表时间:2011-09-19  
流水号这东西需要持久化吧,只在内存里记录的话系统一重启就出问题了
0 请登录后投票
   发表时间:2011-09-19  
什么情况下要生成循环的可重复流水号?
0 请登录后投票
   发表时间:2011-09-19  
hareamao 写道
方法的头一段可以改成:

        int n = ++serialNumber;
        serialNumber %= 999999;


另外,你的程序不考虑系统重启的可能性么?


小小纠正一下,按楼主要求,应该是
        int n = serialNumber = serialNumber%999999 + 1;

应该是可以不同步整个方法的吧,n属于局部变量,只要同步serialNumber部分就可以了。
0 请登录后投票
   发表时间:2011-09-19  
AnotherTomorrow 写道
hareamao 写道
方法的头一段可以改成:

        int n = ++serialNumber;
        serialNumber %= 999999;


另外,你的程序不考虑系统重启的可能性么?


小小纠正一下,按楼主要求,应该是
        int n = serialNumber = serialNumber%999999 + 1;

应该是可以不同步整个方法的吧,n属于局部变量,只要同步serialNumber部分就可以了。


有问题吧,这样一直加下去,不考虑int溢出吗?

整个操作过程 check - save - get 应该封装为原子操作,同时可以考虑使用jdk的原子变量类来简化过程
0 请登录后投票
   发表时间:2011-09-19  
quxiaoyong 写道
什么情况下要生成循环的可重复流水号?

上峰的要求,小弟只管实现
0 请登录后投票
   发表时间:2011-09-19  
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;
	}
	
}
0 请登录后投票
   发表时间:2011-09-19   最后修改:2011-09-19
单例实现跟你1楼的static实现没有什么区别。
initSerialNumber()什么时候调用?可以考虑放到static代码段中。
另外
for(int i=0, length=6-strbu.length(); i<length; i++){ 
            strbu.insert(0, 0); 
        } 
这里性能不好。
0 请登录后投票
   发表时间:2011-09-19  
一个sequence就搞定了,要这么麻烦?
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics