最近老是被運營抱怨訂單號太長不方便輸入,可是如果隨機生成太短的訂單號又容易重復,造成客戶提交訂單失敗。
夜不能眠下寫了這個工具,完美解決了問題,在這里分享下,由於時間緊張考慮可能不太周到,如發現問題歡迎指教。
import java.util.*; /** * 訂單號生成器 */ public class OrderNoGenerator { private int size; private int length; private List<String> orderNoList; private Set<String> orderNoSet; /** * 訂單號生成器 * <p> * 為了保證生成性能需滿足條件size<10^length/4 * * @param size 保證連續不重讀的數 * @param length 生成隨機數的長度 */ public OrderNoGenerator(int size, int length) { this.size = size; this.length = length; AssertUtils.requireTrue(size < Math.pow(10, length) / 4, "參數不符合要求"); orderNoList = new ArrayList<>(); orderNoSet = new HashSet<>(); } /** * 獲取不重復的隨機數 * * @return */ public synchronized String generatorOrderNo() { String randomNumber = RandomUtils.randomNumber(length); while (orderNoSet.contains(randomNumber)) { randomNumber = RandomUtils.randomNumber(length); } orderNoList.add(randomNumber); orderNoSet.add(randomNumber); reduce(); return randomNumber; } private void reduce() { if (orderNoList.size() >= size * 2) { List<String> removes = orderNoList.subList(0, size); orderNoSet.removeAll(removes); removes.clear(); } } }
/** * 隨機數工具 */ public class RandomUtils { public static int[] nums = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; public static Random random = new Random(); /** * 生成隨機數字 * * @param length 隨機數長度 * @return */ public static String randomNumber(int length) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < length; i++) { int index = random.nextInt(10); builder.append(nums[index]); } return builder.toString(); } }
public class AssertUtils { public static void requireTrue(boolean value, String msg) { if (!value) { throw new RuntimeException(msg); } } }
//測試代碼 private static intcounts = 0; private static Object lock = 0; //模擬生成200個訂單號一百萬次 public static void main(String[] args) { //訂單號格式為 yyyyMMddhhmmss+3位隨機數 //假設連續生成200單 OrderNoGenerator generator = new OrderNoGenerator(200, 3); Map<String, String> map = new HashMap<>(); for (int x = 0; x < 10; x++) { new Thread(() -> { int count = 0; for (int j = 0; j < 10000; j++) { for (int i = 0; i < 200; i++) { String randomNumber = generator.generatorOrderNo(); synchronized (lock) { counts++; if (counts > 200) { map.clear(); } if (map.containsKey(randomNumber)) { count++; System.out.println("訂單號重復"); } map.put(randomNumber, ""); } } } System.out.println("線程"+Thread.currentThread().getId()+"訂單號重復" + count + "次"); }).start(); } }
轉載注明出處:https://www.cnblogs.com/cblogs/p/7396108.html
