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()); } }