import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;
public class CodeCreator {
public static final String PREFIX_REGEX = "[A-z]{1,3}";
private static long workerId = 0;
static {
InetAddress address;
try {
address = InetAddress.getLocalHost();
} catch (final UnknownHostException e) {
throw new IllegalStateException("Cannot get LocalHost InetAddress, please check your network!");
}
byte[] ipAddressByteArray = address.getAddress();
int i1 = ipAddressByteArray[1];
int i2 = ipAddressByteArray[2];
int i3 = ipAddressByteArray[3];
i1 = i1 < 0 ? 256 + i1 : i1;
i2 = i2 < 0 ? 256 + i2 : i2;
i3 = i3 < 0 ? 256 + i3 : i3;
// workerId = (long) ((((i1 << Byte.SIZE) + i2) << Byte.SIZE) + i3);
workerId = (long) ((i2 << Byte.SIZE) + i3);
}
private static ReentrantLock instanceLock = new ReentrantLock();
private static Map<String, CodeCreator> instances = new HashMap<>();
private String prefix;
private ReentrantLock lock = new ReentrantLock();
private int number = 0;
private int maxNumber = 10;
private long lastTime = 0;
/**
* @param prefix 编码前缀;1-3个字符
* @return
*/
public static CodeCreator getInstance(String prefix) {
return getInstance(prefix, 20);
}
/**
* @param prefix 编码前缀;1-3个字符
* @param len 编码总长度,最少20
* @return
*/
public static CodeCreator getInstance(String prefix, int len) {
if (prefix == null || !prefix.matches(PREFIX_REGEX))
throw new IllegalArgumentException("prefix must be 1 - 3 character");
if (len - prefix.length() < 16 || len - prefix.length() > 25) {
throw new IllegalArgumentException("length except prefix must between 16 and 25!");
}
String key = prefix + len;
if (!instances.containsKey(key)) {
instanceLock.lock();
try {
if (!instances.containsKey(key)) {
instances.put(key, new CodeCreator(prefix, len));
}
} finally {
instanceLock.unlock();
}
}
return instances.get(key);
}
private CodeCreator(String prefix, int len) {
this.prefix = prefix;
len = len - 10 - 5 - this.prefix.length();
while (len-- > 1) {
maxNumber = maxNumber * 10;
}
}
public String next() {
NextNumber nextNumber = getNextNumber();
StringBuilder sb = new StringBuilder();
sb.append(prefix).append(nextNumber.time);
sb.append(String.valueOf(100000 + workerId).substring(1));
// sb.append(prefix).append(nextNumber.time * 100000 + workerId);
if (maxNumber >= 10) {
long index = maxNumber + nextNumber.index;
if (index >= 10)
sb.append(String.valueOf(index).substring(1));
}
return sb.toString();
}
public long nextNumber() {
NextNumber nextNumber = getNextNumber();
if (nextNumber.time * 10000 + workerId > (Long.MAX_VALUE / maxNumber))
throw new BusinessException("BIZ_UTIL", "根据你的设定,结果大于Long类型的上限,无法返回结果");
return (nextNumber.time * 10000 + workerId) * maxNumber + nextNumber.index;
}
private NextNumber getNextNumber() {
lock.lock();
try {
long time = System.currentTimeMillis() / 1000;
if (lastTime != time) {
lastTime = time;
number = 0;
} else {
if (++number >= maxNumber) {
while (true) {
try {
Thread.sleep(10);
} catch (Exception e) {
}
time = System.currentTimeMillis() / 1000;
if (lastTime != time) {
lastTime = time;
number = 0;
break;
}
}
}
}
NextNumber nextNumber = new NextNumber();
nextNumber.time = time;
nextNumber.index = number;
return nextNumber;
} finally {
lock.unlock();
}
}
class NextNumber {
long time;
long index;
}
}
鸣谢:尚冠男