在 Servlet 中使用 timemillis 方法为每个请求创建唯一的请求 ID

creating unique request id for each request using timemillis method in Servlet

我正在开发一个 servlet,我需要为每个请求提供唯一的请求并将每个请求参数存储在审计中 table。 如果我尝试通过回头查看 table 的前一个 ID 来增加一个值,我担心数据库 tables 上的脏读操作。 我想知道当请求到达 servlet 时是否使用以毫秒为单位的时间来解决这个问题。 恐怕如果同一个 servlet 可能同时从其他地理位置发出任何其他请求,那么 java.lang.System.currentTimeMillis() 将与其他请求相同。 让我 post 产生这种怀疑的原因是我相信 servlet 的多线程行为一次接受一个请求,然后基于某种算法为每个请求跨越 cpu 个周期。

不保证System.currentTimeMillis()在被多线程调用时是唯一的。过去遇到这种情况时,我使用 AtomicLong 来创建唯一 ID - 这个 class 的 getAndIncremenet 应该是 lock-free(因此相当有效)大多数 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);
        }
    }
}

连synchronized也是错的。您可能会在时间非常接近的两个请求中获得相同的 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 序列。