方案一:
如果没有并发,订单号只在一个线程内产生,那么由于程序是顺序执行的,不同订单的生成时间戳正常不同,因此用时间戳+随机数(或自增数)就可以区分各个订单。如果存在并发,且订单号是由一个进程中的多个线程产生的,那么只要把线程ID添加到序列号中就可以保证订单号唯一。如果存在并发,且订单号是由同一台主机中的多个进程产生的,那么只要把进程ID添加到序列号中就可以保证订单号唯一。如果存在并发,且订单号是由不同台主机产生的,那么MAC地址、IP地址或CPU序列号等能够区分主机的号码添加到序列号中就可以保证订单号唯一。
方案二:
时间戳+用户ID+几个随机数+乐观锁。
方案三:
用redis的原子递增,做好高可用集群。
方案四(非纯数字):
java自带uuid。
事例代码
java获取线程ID
Thread.currentThread().getId()
java获取进程ID
// get name representing the running Java virtual machine.
String name = ManagementFactory.getRuntimeMXBean().getName();
System.out.println(name);
// get pid
String pid = name.split("@")[0];
System.out.println("Pid is:" + pid);java获取mac地址
InetAddress ia = InetAddress.getLocalHost();
byte[] mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress();
String macStr = DatatypeConverter.printHexBinary(mac);方案四:
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
public class UuidUtils {
private static AtomicLong id;
/**
* 生成Long 类型唯一ID
*/
public synchronized static Long getId() {
//如果需要更长 或者更大冗余空间, 只需要 time * 10^n 即可
//当前可保证1毫秒 生成 10000条不重复
Long time = Long.valueOf(new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()))*10000;
if (id == null) {
id = new AtomicLong(time);
return id.get();
}
if (time <= id.get()) {
id.addAndGet(1);
} else {
id = new AtomicLong(time);
}
return id.get();
}
public static void main(String[] args) throws InterruptedException {
Set<Long> set = new TreeSet<>();
for (int i = 0; i < 100; i++) {
new Thread(() ->
{
Long id = getId();
set.add(id);
System.out.println(id);
}
).start();
}
Thread.sleep(5000);
int size = set.size();
System.out.println(size);
}
}组合
package com.zz.meridian.utils;
import java.lang.management.ManagementFactory;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
public class NumberIdUtils {
private static AtomicLong id;
public static AtomicLong id() {
return id;
}
/**
* 生成Long 类型唯一ID
*/
public static Long getId2() {
long id = Thread.currentThread().getId();
// get name representing the running Java virtual machine.
String name = ManagementFactory.getRuntimeMXBean().getName();
// System.out.println(name);
// get pid
String pid = name.split("@")[0];
long l = 0;
try {
l = Long.parseLong(pid);
} catch (NumberFormatException e) {
}
return id + l;
}
/**
* 生成Long 类型唯一ID
*/
// public static synchronized Long getId() {
public static synchronized Long getId() {
//如果需要更长 或者更大冗余空间, 只需要 time * 10^n 即可
//当前可保证1毫秒 生成 10000条不重复
Long time =Long.valueOf(new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date())) *10000;
for (int i = 0; i <3 ; i++) {
time=time+(getId2()+Math.round(Math.random() * 10000));
}
if (id == null) {
id = new AtomicLong(time);
return id.get();
}
if (time <= id.get()) {
id.addAndGet(1);
} else {
id = new AtomicLong(time);
}
return id.get();
}
public static void main(String[] args) throws InterruptedException {
List<Long> set = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
new Thread(() ->
{
Long id = getId();
set.add(id);
System.out.println(id);
}
).start();
}
Thread.sleep(10000);
int size = set.size();
System.out.println(size);
Map<Long, Long> collect = set.stream().collect(Collectors.groupingBy(Long::longValue, Collectors.counting()));
collect.forEach((k,v)->{
System.err.println(k+"==="+v);
});
}
}总结
以上所述是小编给大家介绍的java web在高并发和分布式下实现订单号生成唯一的解决方案
版权声明:本文为qq_38567039原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。