Java 使用新日期()作为唯一标识符
假设我有一个每秒创建1000个实体的过程。 对于这些实体中的每一个,我称之为setter:Java 使用新日期()作为唯一标识符,java,date,datetime,unique,uniqueidentifier,Java,Date,Datetime,Unique,Uniqueidentifier,假设我有一个每秒创建1000个实体的过程。 对于这些实体中的每一个,我称之为setter: newEntity.setDate(new Date()); 1) 两个实体是否可能收到相同的日期?或者可以安全地假设我确实获得了日期字段的唯一标识符效果吗 2) 如果问题#1的答案是:“是”-让我们稍微调整一下: 让我们创建一个函数: public static synchronized Date getDate() { return new Date(); } 现在行吗 newEntit
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();
}
谢谢。1)如果您的CPU足够快,是的,两个实体可能会接收到表示相同时间的不同对象(即,它不会按您想要的方式工作)
2) 同样,如果您的CPU速度足够快,它将无法工作。一个简单的测试表明,连续两次调用
new Date()
可以返回相同的日期。使方法同步不会产生任何影响
如果您只需要一个唯一的ID,那么可以使用AtomicInteger计数器
和返回计数器.getAndIncrement()代码>用于新ID
注:使用System.nanotime()
也没有帮助,因为分辨率取决于操作系统和处理器,并且通常足够低,以至于两个连续调用也可以返回相同的结果
编辑
您的第四个建议是在同步方法中睡眠一秒钟,这可能会解决您的唯一性问题(尽管正如yshavit所指出的,javadoc中没有任何东西可以保证这一点)。但是请注意,使用日期作为唯一id本身是一个坏主意:日期是可变的,因此调用代码可以使用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;
}
private static final Set usedIds=new HashSet();
公共静态同步长getUniqueId(){
长毫;
做{
毫秒=System.currentTimeMillis();
}而(!usedIds.add(millis));
返回毫秒;
}
日期
具有毫秒精度。因此,这可以归结为,“是否可以在毫秒内调用两次new Date()
?答案显然是肯定的。此外,System.currentTimeMillis()
,这只会使问题变得更糟
最好使用AtomicInteger
(或AtomicLong
)中的一个简单计数器
此外,这是“契约式设计”思维的一个很好的练习。currentTimeMillis
和nanoTime
的规范都没有说它们将返回唯一的数字,因此您不能假设它们会返回唯一的数字(事实上,用于nanoTime的Javadoc特别指出,“不保证值的更改频率”)。即使它们今天碰巧出现在您的计算机上(可能没有),当CPU在5年内变得更快,并且您能够每秒调用nanoTime()
一万亿次时,会发生什么
继续你被承诺过的事情(假设你相信承诺!),而不是你今天碰巧看到的事情。这通常是正确的,但对于任何与时间或并发性相关的事情来说尤其如此。不幸的是,1.不是一个好的解决方案
你的建议都不符合规定。
在同步方法中,您可以添加具有正确粒度(1毫秒)的睡眠:无论如何,非常难看。
您的其他建议。
System.nanotime()我想现在应该是你的uuid了,太长了。
在这种情况下,解决方法可以是将延迟设置为1纳秒,并且:
long start = System.nanotime();
while(start + delay < System.nanoTime());
long start=System.nanotime();
而(启动+延迟
new Date()
读取系统时钟-可以在同一毫秒内进行多次读取。同步不会改变这一点(除非使完成一项操作所需的时间稍微延长)。不要使用日期作为唯一标识符。睡眠一秒钟与问题的开始参数之一不符也不值得。该过程“每秒创建1000个实体”。如果每个实体至少需要一秒钟的时间来创建,则很难每秒创建1000个实体。+1使方法同步不会产生任何影响”!!