在 java 中每毫秒生成 4 位多个唯一 ID
Generating 4 digits of multiple unique IDs per millisecond in java
我正在使用 batchupdate
插入数据库。我需要生成 id 的实际 10 位数字,其中前六位数字将保持不变,即 yyMMdd
我正在尝试根据本地日期将四个唯一数字附加到此 yyMMdd
模式块。
问题是,它会生成大量重复项,因为 FOR
循环在 ms
.
中提前 运行
Expected Pattern : 210609xxxx where 210609 is taken from yyMMdd
pattern of LocalDate
in java and xxxx needs to be unique for even if FOR
loop calls this method multiple times per millisecond.
public Long getUniquedeltaId() {
final Long LIMIT = 10000L;
final Long deltaId = Long.parseLong(Long.toString(Long.parseLong((java.time.LocalDate.now()
.format(DateTimeFormatter
.ofPattern("yyMMdd")))))
.concat(Long.toString(System.currentTimeMillis() % LIMIT)));
System.out.println("deltaId"+deltaId);
return deltaId;
我尝试使用 System.nanoTime()
但它只返回一个 uniqueId。
如果您在某个时间点需要一个非常简单的唯一 ID 列表,您可以使用以下方法:
package example;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
final String prefix = "20210609";// hardcoded prefix for the example
final List<String> uniqueIds = ThreadLocalRandom.current().ints(0, 10_000)// ints from 0 to 10000 (exclusive) -> every possible 4 digit number
.distinct()// only distinct numbers
.limit(1000L)// exactly 1000 (up to 10000 possible)
.mapToObj(v -> String.format("%04d", v))// always 4 digits (format as string, lpad with 0s
.map(v -> prefix + v)// add our prefix
.collect(Collectors.toList());
System.out.println(uniqueIds);
}
}
如果您需要一次为您提供一个唯一 ID 的组件,您可以使用此 class:
package example;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
public class IdGenerator {
private static final int LENGTH = 10_000;
private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyMMdd");// unlike SimpleDateFormat, this is thread-safe
private final Object monitor;
private final AtomicInteger offset;
private final AtomicBoolean generationInProgress;
private volatile int[] ids;
private volatile LocalDate lastGeneratedDate;
public IdGenerator() {
this.monitor = new Object();
this.offset = new AtomicInteger(0);
this.generationInProgress = new AtomicBoolean(false);
this.ids = new int[LENGTH];
this.lastGeneratedDate = LocalDate.MIN;
}
public String nextId() throws InterruptedException {
final LocalDate currentDate = LocalDate.now();
while (this.lastGeneratedDate.isBefore(currentDate)) {
if (this.generationInProgress.compareAndSet(false, true)) {
this.ids = ThreadLocalRandom.current().ints(0, LENGTH)
.distinct()
.limit(LENGTH)
.toArray();
this.offset.set(0);
this.lastGeneratedDate = currentDate;
this.generationInProgress.set(false);
synchronized (this.monitor) {
this.monitor.notifyAll();
}
}
while (this.generationInProgress.get()) {
synchronized (this.monitor) {
this.monitor.wait();
}
}
}
final int myIndex = this.offset.getAndIncrement();
if (myIndex >= this.ids.length) {
throw new IllegalStateException("no more ids today");
}
return currentDate.format(DTF) + String.format("%04d", this.ids[myIndex]);
}
}
请注意,您的模式每天只允许 10000 个唯一 ID。您将自己限制为每天 4 位数 (10^4 = 10000
)。
我正在使用 batchupdate
插入数据库。我需要生成 id 的实际 10 位数字,其中前六位数字将保持不变,即 yyMMdd
我正在尝试根据本地日期将四个唯一数字附加到此 yyMMdd
模式块。
问题是,它会生成大量重复项,因为 FOR
循环在 ms
.
Expected Pattern : 210609xxxx where 210609 is taken from
yyMMdd
pattern ofLocalDate
in java and xxxx needs to be unique for even ifFOR
loop calls this method multiple times per millisecond.
public Long getUniquedeltaId() {
final Long LIMIT = 10000L;
final Long deltaId = Long.parseLong(Long.toString(Long.parseLong((java.time.LocalDate.now()
.format(DateTimeFormatter
.ofPattern("yyMMdd")))))
.concat(Long.toString(System.currentTimeMillis() % LIMIT)));
System.out.println("deltaId"+deltaId);
return deltaId;
我尝试使用 System.nanoTime()
但它只返回一个 uniqueId。
如果您在某个时间点需要一个非常简单的唯一 ID 列表,您可以使用以下方法:
package example;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
final String prefix = "20210609";// hardcoded prefix for the example
final List<String> uniqueIds = ThreadLocalRandom.current().ints(0, 10_000)// ints from 0 to 10000 (exclusive) -> every possible 4 digit number
.distinct()// only distinct numbers
.limit(1000L)// exactly 1000 (up to 10000 possible)
.mapToObj(v -> String.format("%04d", v))// always 4 digits (format as string, lpad with 0s
.map(v -> prefix + v)// add our prefix
.collect(Collectors.toList());
System.out.println(uniqueIds);
}
}
如果您需要一次为您提供一个唯一 ID 的组件,您可以使用此 class:
package example;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
public class IdGenerator {
private static final int LENGTH = 10_000;
private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyMMdd");// unlike SimpleDateFormat, this is thread-safe
private final Object monitor;
private final AtomicInteger offset;
private final AtomicBoolean generationInProgress;
private volatile int[] ids;
private volatile LocalDate lastGeneratedDate;
public IdGenerator() {
this.monitor = new Object();
this.offset = new AtomicInteger(0);
this.generationInProgress = new AtomicBoolean(false);
this.ids = new int[LENGTH];
this.lastGeneratedDate = LocalDate.MIN;
}
public String nextId() throws InterruptedException {
final LocalDate currentDate = LocalDate.now();
while (this.lastGeneratedDate.isBefore(currentDate)) {
if (this.generationInProgress.compareAndSet(false, true)) {
this.ids = ThreadLocalRandom.current().ints(0, LENGTH)
.distinct()
.limit(LENGTH)
.toArray();
this.offset.set(0);
this.lastGeneratedDate = currentDate;
this.generationInProgress.set(false);
synchronized (this.monitor) {
this.monitor.notifyAll();
}
}
while (this.generationInProgress.get()) {
synchronized (this.monitor) {
this.monitor.wait();
}
}
}
final int myIndex = this.offset.getAndIncrement();
if (myIndex >= this.ids.length) {
throw new IllegalStateException("no more ids today");
}
return currentDate.format(DTF) + String.format("%04d", this.ids[myIndex]);
}
}
请注意,您的模式每天只允许 10000 个唯一 ID。您将自己限制为每天 4 位数 (10^4 = 10000
)。