如Java博客文章Beware of System.nanoTime()中所述,在x86系统上,Java的System.nanoTime()使用CPU特定计数器返回时间值.现在考虑以下用于测量呼叫时间的情况:
long time1= System.nanoTime();
foo();
long time2 = System.nanoTime();
long timeSpent = time2-time1;
Run Code Online (Sandbox Code Playgroud)
现在在多核系统中,可能是在测量time1之后,线程被调度到不同的处理器,其计数器小于先前CPU的计数器.因此,我们可以得到time2中的值,该值小于 time1.因此,我们将在timeSpent中得到负值.
考虑到这种情况,是不是System.nanotime现在几乎没用?
我知道改变系统时间不会影响纳米时间.这不是我上面描述的问题.问题是每个CPU都会在打开后保留不同的计数器.与第一个CPU相比,第二个CPU上的计数器可以更低.由于在获取time1之后OS可以将线程调度到第二个CPU,因此timeSpent的值可能不正确甚至是负数.
在Java应用程序中,我希望能够在操作开始时获取时间戳,并能够定期检查操作运行的时间.问题是:我不希望受到网络时间协议的影响,或者管理员改变时间,或任何可能突然调整时间的东西.我想要一个单调增加的时间价值.我相信这会排除java.util.Date,Time和Calendar.
JRE中是否存在单调增加时间戳的某些来源?
我正在制作一种概率模拟器,它可以运行一定的时间,也可以进行一定的重复次数.我正在寻求优化它,它目前是多线程的,每个ProbabilityWorker
扩展Thread
,主程序将自动分配n
线程,n
但是有很多线程可用(例如:在我的Core i3-7100U上,这是4).
我正在分析这个的性能,我意识到我用来获取结束时间的当前时间的方法会导致很多开销.
对于可以"运行一段时间"的模式,我将new Date
对象作为循环条件的一部分,然后我将其更改为更快System.currentTimeMillis()
以尝试并节省时间,但我注意到即使这会导致开销.
我的run
功能看起来像这样:
public void run() {
if (mode) {
while (completed < repitions) {
resultSet[randy.nextInt(o)]++;
completed++;
}
} else {
while (System.currentTimeMillis() < endTime) {
resultSet[randy.nextInt(o)]++;
completed++;
}
}
done = true;
}
Run Code Online (Sandbox Code Playgroud)
其中mode
是true
如果重复的量运行,randy
是随机的,o
是可能结果的量,并且endTime
是在毫秒结束点时,系统时间(其可以被修改,程序需要在几秒钟的量,并endTime
通过计算出的当前时间加secondsInput * 1000
).
另外,在同一个Core i3-7100U上,这些是我的性能统计数据:
DE-WEY-LAPTOP:/mnt/c/Users/danny/Documents/Programming/Data Structures/Probability$ java Main -n 10000000000
Running 10000000000 repitions of …
Run Code Online (Sandbox Code Playgroud) 我们有一个主进程写入日志的情况。
然后它产生多个写入自己日志的工作进程。(我希望工人通过 master 登录,但由于某种原因,这个想法遭到了抵制。)
我想知道的是,我可以相信最终出现在多个文件中的时间戳彼此一致吗?即,如果我将日志文件合并到一个按即时排序的单个文件中,事件的顺序是否正确?跨所有可能的操作系统?
我问这个的原因是我有一个奇怪的情况,在主进程报告工作进程有错误后两秒钟,工作进程似乎记录了错误。就好像师父能够预知未来。(我猜主人也是时间领主,但是呃……)