有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java没有获得唯一的时间戳

我正在为要存储的对象生成唯一ID

我把时间戳包括在里面

但是我运行了for循环

    for (int i = 0; i < 100; i++) {

        long time = Calendar.getInstance().getTimeInMillis();
        st = Integer.toHexString((int) time);
        System.out.printf("%d %s %d %n", i, st, st.length());
    }

我没有得到唯一的答案

我插入了Thread.sleep(15),然后它给了我唯一的值

是否有其他方法可以获得唯一值


共 (4) 个答案

  1. # 1 楼答案

    以下是3种唯一时间戳的方法:

    /** WITH LOCK */
    private static long lastTs1 = Long.MIN_VALUE;
    private static final long uniqueTs1() {
        long unique_ts = System.currentTimeMillis();
        synchronized (SmtpServer.class) { lastTs1 = unique_ts = unique_ts > lastTs1 ? unique_ts : lastTs1 + 1; }
        return unique_ts;
    }
    
    /** WITHOUT LOCK */
    private static AtomicLong lastTs2 = new AtomicLong(Long.MIN_VALUE);
    private static final long uniqueTs2() { return lastTs2.updateAndGet((v)->Math.max(v+1, System.currentTimeMillis())); }
    
    /** WITHOUT LOCK, WITHOUT extra class */
    private static AtomicLong lastTs3 = new AtomicLong(Long.MIN_VALUE);
    private static final long uniqueTs() {
        long expect, next = System.currentTimeMillis();
        do {
            expect = lastTs3.get();
            if(expect >= next) next = expect + 1;
        } while(!lastTs3.compareAndSet(expect, next));
        return next;
    }
    
  2. # 2 楼答案

    我会使用一个简单的longint^{}更简单,而且是线程安全的。 另一种可能是使用UUID.randomUUID(),但它是UUID,而不是数值

  3. # 3 楼答案

    试试这个

    public class DateTimeService {
    
        @Autowired
        private Clock clock;
        private LocalDateTime current;
    
        @PostConstruct
        public void init() {
            current = LocalDateTime.now(clock);
        }
    
        public synchronized LocalDateTime getUniqueTimestamp() {
            LocalDateTime now = LocalDateTime.now(clock);
            if (current.isEqual(now) || current.isAfter(now)) {
                current = current.plus(1, ChronoUnit.MICROS);
            } else {
                current = now;
            }
            return current;
        }
    }
    
  4. # 4 楼答案

    您的循环在两次迭代之间花费的时间少于1ms,因此时间戳不会改变(这就是为什么添加一个sleep调用会给时钟移动时间的原因)

    您最好使用库调用,如palacsint建议的那样,或者自己管理UID。执行此操作的可能性包括获取最后发布的ID并递增,尽管这对于多线程有问题