序列号组成:前缀 + 日期 + 尾数
例如: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次访问,测试结果没有发生重复。