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