import java.time.Instant;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.FastDateFormat;
/**
* 创建订单编号
*
* @project sorder
* @fileName MakeCode.java
* @Description
* @author light-zhang
* @date 2018年3月11日下午12:19:25
* @version 1.0.0
*/
public abstract class MakeCode {
/**
* 订单号生成计数器
*/
private static long orderNumCount = 0L;
/**
* 每毫秒生成订单号数量最大峰值
*/
private static final int maxPerMSECSize = 2000;
private static final String[] machine = new String[] { "00100", "00200", "00300", "00400" };// 这个很重要,如果是分配的不同机器,随机分配机器编码要不一致
private static final FastDateFormat date_pattern = FastDateFormat.getInstance("yyyyMMdd");
private static final FastDateFormat seconds_pattern = FastDateFormat.getInstance("HHmmss");
/**
* 并发下面容易产生重复的订单号,给传入的PKID枷锁,保证资源安全的同时,性能也有所下降 订单生成策略为: 时间20180511
* +机器编码(我这里临时填写的是00100),在本台机器上生成订单编号的标识,如果分开部署,则此处的机器码需要变更,防止出现意外重复 +二位随机数
* +lock的hash-code编码,这里有个并发下的性能问题 +时间时分秒 +递增参数值
*
* @param lock
* 生成的UUID32位参数
* @return
*/
public static String makeOrderCode(String lock) {
final StringBuilder builder = new StringBuilder(35);
synchronized (lock) {// 锁住传入的lock[UUID]
if (orderNumCount >= maxPerMSECSize) { // 计数器到最大值归零,目前1毫秒处理峰值2000个
orderNumCount = 0L;
}
orderNumCount++;
builder.append(date_pattern.format(Instant.now().toEpochMilli()));// 取系统当前时间作为订单号变量前半部分
builder.append(machine[getMachine()]);// 当前服务机器分配的随机码
builder.append(getNumber());// 随机数
builder.append(Math.abs(lock.hashCode()));// HASH-CODE
builder.append(seconds_pattern.format(Instant.now().toEpochMilli())); // 获取毫秒产生参数
builder.append(orderNumCount);// 计数器的值
return builder.toString();
}
}
/**
* 产生随机的2位数
*
* @return
*/
public static String getNumber() {
final Random rad = new Random();
String result = Integer.toString(rad.nextInt(100));
if (Integer.compare(result.length(), 1) == 0) {
result = "0".concat(result);
}
return result;
}
/**
* 随机抽取机器码
*
* @return
*/
public static int getMachine() {
final Random rad = new Random();
return rad.nextInt(machine.length);
}
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
for (int i = 0; i < 100; i++) {
set.add(makeOrderCode(StringUtils.replace(UUID.randomUUID().toString(), "-", "")));
}
System.out.println(set.size());
}
}