我正在研究一个servlet,我需要为每个请求提供一个唯一的请求,并将每个请求参数存储在一个审计表中。 如果我试图通过回顾前一个id的表来增加值,我担心数据库表上的脏读操作。 我想知道当请求到达servlet时是否以毫秒为单位使用时间来解决这个问题。 我担心如果同一个servlet可以同时从其他地理位置发出任何其他请求,那么java.lang.System.currentTimeMillis()将对于其他请求来说是相同的。 让我发布这个疑问的原因是我相信servlet的多线程行为是一次请求一个请求,然后根据某些算法为每个请求跨越cpu周期。
答案 0 :(得分:2)
多个线程调用时,System.currentTimeMillis()
不保证是唯一的。在过去遇到这种情况时,我使用了AtomicLong来创建唯一的ID - 这个类的getAndIncremenet
在大多数JVM上应该是无锁的(因此效率相当高)
public class IdUtil {
private static final AtomicLong counter = new AtomicLong(System.currentTimeMillis());
// return a single id
public static long getId() {
return counter.getAndIncrement();
}
// return a block of ids
public static Queue<Long> getIds(long span) {
long max = counter.addAndGet(span);
Queue<Long> queue = new ArrayDeque<>(span);
for(int i = max - span; i < max; i++) {
queue.add(i);
}
}
}
答案 1 :(得分:0)
即使是同步它也是错误的。您可以在非常接近的时间内获得两个请求的相同ID。您应该更好地使用随机的长序列号。
private static final Random r = new Random(); // <- shared resource
// ...
long id = r.nextLong();
或
private static final AtomicLong counter = new AtomicLong(System.currentTimeMillis()); // <- shared resource
// ...
long id = counter.getAndIncrement();
counter
初始化为毫秒,因此在程序重启后它不会提供相同的id序列。