使用new Date()作为唯一标识符

4

假设我有一个进程每秒创建1000个实体。对于这些实体中的每一个,我都会调用setter方法:

newEntity.setDate(new Date());

1) 两个实体是否可能接收相同的日期?或者可以安全地假定我会得到日期字段的唯一标识符效果?

2) 如果问题#1的答案是:“是”,那么让我们进行小修改:创建一个函数:

public static synchronized Date getDate() {
     return new Date();
}

现在它能工作吗?

newEntity.setDate(getDate());

3) 那么这个怎么办呢?

System.nanoTime()?

编辑 4)关于什么?

public static synchronized Date getDate() {
     Thread.Sleep(1000);
     return new Date();
}

谢谢。

2
new Date() 读取系统时钟 - 可以在同一毫秒内进行多次读取。同步不会改变这一点(除了使完成操作所需的时间略微更长)。不要使用日期作为唯一标识符。 - Greg Kopff
4个回答

10

一项简单的测试表明,连续调用两次new Date()可能返回相同的日期。将方法设为同步也不会有任何区别。

如果您只需要一个唯一的ID,可以使用AtomicInteger counter并使用return counter.getAndIncrement();来获得新的ID。

ps:即使是使用System.nanotime()也无济于事,因为其分辨率取决于操作系统和处理器,并且通常足够低,以至于连续两次调用可能返回相同的结果。


编辑

在同步方法中睡眠一秒钟的第4个提议可能会解决您的唯一性问题(尽管如yshavit所指出的那样,javadoc中没有保证)。但请注意,使用日期作为唯一标识本身就是一个坏主意:日期是可变的,因此调用代码可以使用setTime方法(无意或有意)更改其ID。

最后,如果您确实希望您的ID与日期相关,则可以使用表示自公元纪元以来的毫秒数的长整型,并跟踪现有的ID - 类似于这样:

private static final Set<Long> usedIds = new HashSet<> ();
public static synchronized long getUniqueId() {
    long millis;
    do {
        millis = System.currentTimeMillis();
    } while (!usedIds.add(millis));
    return millis;
}

1
值得注意的是,休眠一秒与问题的一个开放参数相冲突,即“每秒创建1000个实体的进程”。如果每个实体至少需要一秒钟才能创建,那么每秒创建1000个实体将会很困难。 - yshavit
千万不要对“将方法同步化不会产生任何区别”的说法表示赞同!请立即给出+1。 - Andremoniy

4
Date 具有毫秒精度。因此,问题就在于“是否可能在一毫秒内两次调用 new Date()?”答案显然是肯定的。此外,System.currentTimeMillis()并不完全准确到毫秒,这只会使问题更加复杂。
你最好使用来自 AtomicInteger(或 AtomicLong)的简单计数器。
此外,这是一个“契约式设计”思想的好练习。既不 currentTimeMillis 也不 nanoTime 的规范说明它们将返回唯一的数字,因此您不能假设它们会这样做(实际上,nanoTime 的 Javadoc 明确指出“不保证值的变化频率”)。即使它们今天在您的计算机上偶然如此(它们可能不会),那么当 CPU 在 5 年后变得更快时,您能够每秒调用 nanoTime() 一万亿次,会发生什么?

相信你所承诺的(假设你信任这个承诺!),而不是你今天偶然观察到的。这通常是正确的,尤其是与时间或并发相关的事情。


0

很遗憾,第一种方法不是一个好的解决方案。
你的提议都不太行,如它们所表述的那样。
在同步方法中,你可以添加一个正确粒度(1毫秒)的睡眠:非常丑陋。
你的另一个提议。
我猜System.nanotime()现在应该是你的uuid,所以是一个长整型。
在这种情况下,一个解决方法是设置一个1纳秒的延迟和:

long start = System.nanotime();  
while(start + delay < System.nanoTime());  

0

1) 如果你的CPU足够快,是有可能两个实体接收到代表同一时间的不同对象(也就是说它不会按照你想要的方式工作)。

2) 同样地,如果你的CPU足够快,它也不会起作用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接