序列号组成:前缀 + 日期 + 尾数
比如:ZC20140806000001
总共两个组成:一个枚举类。一个静态生成器。另外须要设计自己主动任务每日凌晨或其它时间重置一次尾数。
先上枚举类:
package com.boxmeal.base.constant.common;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 序列号生成枚举
* @author bling
*
*/
public enum SNEnum {
// 订单编号
SUIT("tcd",new AtomicInteger(0));
private String prefix;
private AtomicInteger count;
private SNEnum(String prefix,AtomicInteger count) {
this.prefix = prefix;
this.count = count;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public void setCount(AtomicInteger count) {
this.count = count;
}
public String getPrefix() {
return prefix;
}
public AtomicInteger getCount() {
return count;
}
}
枚举类是为了控制參数保证统一性。
再上生成器类:
package com.boxmeal.base.util;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;
import com.boxmeal.base.constant.common.SNEnum;
/**
* 序列号生成器,每日自己主动从1開始增长
* @author bling
*
*/
public class SNGenerater {
/**
* 日期格式化
*/
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
/**
* 数字格式化
*/
private static final DecimalFormat decimalFormat = new DecimalFormat("000000");
/**
* 序列号产生器
* @param sn
* @return
*/
public final static String genSuitSN(SNEnum sn){
String prefix = sn.getPrefix();
String dateStr = SNGenerater.dateFormat.format(new Date());
String suffix = SNGenerater.decimalFormat.format(sn.getCount().incrementAndGet());
return prefix + dateStr + suffix;
}
/**
* 重置序列号生成器:自己主动任务每日夜间00:00调用一次
*/
public final static void reset(){
SNEnum[] snEnumAry = SNEnum.values();
for(int i=0;i<snEnumAry.length;i++){
snEnumAry[i].setCount(new AtomicInteger(0));
}
}
public static void main(String[] args) {
for(int i=0;i<100;i++){
System.out.println(SNGenerater.genSuitSN(SNEnum.SUIT));
}
SNGenerater.reset();
for(int i=0;i<100;i++){
System.out.println(SNGenerater.genSuitSN(SNEnum.SUIT));
}
}
}
尽管在生成器方法没有加同步关键词,是由于尾数自增是原子操作。
測试类:
package com.boxmeal.test;
import com.boxmeal.base.constant.common.SNEnum;
import com.boxmeal.base.util.SNGenerater;
public class SNTest {
class VisitThread implements Runnable{
@Override
public void run() {
for(int i=0;i<100;i++){
System.out.println(SNGenerater.genSuitSN(SNEnum.SUIT));
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void test(){
for(int i=0;i<20;i++){
new Thread(new VisitThread()).start();
}
}
public static void main(String[] args) {
new SNTest().test();
}
}
开了20个线程并发2000次訪问,測试结果没有发生反复。