如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的值可能不正确甚至是负数.
这是我的简单代码,每秒循环(不需要精确)并在必要时启动作业:
while (true) {
// check db for new jobs and
// kick off thread if necessary
try {
Thread.sleep(1000);
} catch(Throwable t) {
LOG.error("", t);
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码已经好几个月了. 就在昨天,我们开始出现问题,其中一个服务器似乎挂在Thread.sleep(1000)方法中.IOW - 已经过了一天而且Thread.sleep还没有返回.我启动了jconsole并获取有关该线程的信息.
Name: Thread-3
State: TIMED_WAITING
Total blocked: 2 Total waited: 2,820
Stack trace:
java.lang.Thread.sleep(Native Method)
xc.mst.scheduling.Scheduler.run(Scheduler.java:400)
java.lang.Thread.run(Thread.java:662)
Run Code Online (Sandbox Code Playgroud)
Scheduler.java:400是上面的Thread.sleep行.按照我的预期,jconsole输出不会每秒增加"Total wait".事实上,它根本没有变化.我甚至关闭了jconsole并重新启动它,希望可能会强制刷新,但只会再次获得相同的数字.我不知道除了jvm错误地挂在sleep命令上之外还有什么其他的解释.然而,在我这些年里,我对jvm的问题很少,我认为这一定是我的疏忽.
注意:另外需要注意的是没有其他线程处于活动状态. IOW - cpu几乎空闲.我读到某个地方,如果另一个线程处于活动状态,Thread.sleep可能会被合法地饿死,但事实并非如此.
solaris版本:
$ uname -a
SunOS xcmst 5.10 Generic_141415-08 i86pc i386 i86pc
Run Code Online (Sandbox Code Playgroud)
java版本:
$ java -version
java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java …
Run Code Online (Sandbox Code Playgroud) 我有一个使用ntp的盒子,我们运行了几个显示时钟的java程序.我们遇到的问题是,如果有任何事情将系统时间向后踢,我们所有的定时器都会做一些事情,例如让时钟停止动画并等到系统时间回到原来的状态.我需要找到一种方法来检测系统时间何时向后改变并重置所有定时器或一组可以反复调度但仍能防止时钟变化的定时器.
作为一个注释,我已经尝试过石英计时器包,它与普通的java计时器有同样的问题.
我用来java.util.Timer
在我的应用程序中触发作业,但我发现它取决于系统时间:如果调整系统时间,定时器的触发器将受到影响.
例如,如果系统时间回退80秒,计时器将停止工作80秒.
Java有一种System.nanoTime
独立于系统时间的方法,但它似乎无法使用Timer
.
是否有Timer库支持我需要的东西?或者我必须自己实施?
请注意,我不需要精确的当前时间(日期),我需要一个精确的时间间隔