最近老是被运营抱怨订单号太长不方便输入,可是如果随机生成太短的订单号又容易重复,造成客户提交订单失败。
夜不能眠下写了这个工具,完美解决了问题,在这里分享下,由于时间紧张考虑可能不太周到,如发现问题欢迎指教。
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