在 Java 中,System.currentTimeMillis 是否总是返回 >= 前几次调用的值?(它是单调的吗?)
- 2024-10-22 08:28:00
- admin 原创
- 83
问题描述:
https://docs.oracle.com/javase/6/docs/api/java/lang/System.html#currentTimeMillis()说:
返回当前时间(以毫秒为单位)。请注意,虽然返回值的时间单位是毫秒,但值的粒度取决于底层操作系统,可能更大。例如,许多操作系统以几十毫秒为单位来测量时间。
我不清楚是否能保证此代码始终会打印不断增加(或相同)的数字。
while (1) {
System.out.println(System.currentTimeMillis() );
}
解决方案 1:
简短的回答是,System.currentTimeMillis()
不是单调的。 它基于系统时间,因此在时钟调整(例如通过NTP)的情况下,可能会发生变化(向前或向后)。
System.nanoTime()
是单调的,当且仅当底层平台支持时——请参阅Java 错误报告 6458294CLOCK_MONOTONIC
中的评论,以获得关于某些情况的详细说明,这些情况是/不是真的。
(并且,作为额外的轶事,我曾亲眼观察到(几次)System.currentTimeMillis()
跨线程“向后”运行,在没有时钟调整的情况下 - 也就是说,在一个线程中对该方法的调用返回的值低于另一个线程中的调用,即使它在“实时”中按时间顺序发生在它之后)
如果您需要单调源,System.nanoTime()
那么支持单调性的平台是您的最佳选择。
解决方案 2:
不,它并不总是> = 所有先前的调用。
如果您从同一个线程快速连续地调用它几次,它可能不会每次都增加(我知道这是 >= 的 = 部分,但这种行为常常让人感到惊讶)。
如果您从多个线程快速连续地调用它几次,它可能会做很多事情——它可能会跨线程稍微回溯时间,具体取决于实现和随机机会。
最严重的是,如果用户(罕见)或 NTP 同步(可能很常见)调整系统时钟,则该值可能会大幅回溯。
解决方案 3:
由于用户可能会在通话之间改变系统时间,因此不可能保证它会增加。
除此之外,它应该保持增加,因为它表示自纪元以来的毫秒数。如果它是正常的“挂钟时间”,您将不得不担心闰日或夏令时转换时的时间变化。
解决方案 4:
如果您想要一个单调增加的值,您可以执行以下操作。
public enum Time {
;
private static long lastTime;
public synchronized static long increasingTimeMillis() {
long now = System.currentTimeMillis();
if (now > lastTime)
return lastTime = now;
return ++lastTime;
}
}
只要你每秒调用的次数少于一千次,你的增加时间就不会偏离实际时间太远,而是独一无二的。(即使你重新启动应用程序,这也可以起作用)
解决方案 5:
@Mark Rushakoff 是对的;nanoTime()
可能更可靠一些。
附录:请注意这些警告,由@Steven Schlansker 引用。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件