Java中获取比毫秒更精确的时间

上传人:油条 文档编号:8675076 上传时间:2017-09-29 格式:DOCX 页数:7 大小:24.75KB
返回 下载 相关 举报
Java中获取比毫秒更精确的时间_第1页
第1页 / 共7页
Java中获取比毫秒更精确的时间_第2页
第2页 / 共7页
Java中获取比毫秒更精确的时间_第3页
第3页 / 共7页
Java中获取比毫秒更精确的时间_第4页
第4页 / 共7页
Java中获取比毫秒更精确的时间_第5页
第5页 / 共7页
点击查看更多>>
资源描述

《Java中获取比毫秒更精确的时间》由会员分享,可在线阅读,更多相关《Java中获取比毫秒更精确的时间(7页珍藏版)》请在金锄头文库上搜索。

1、 java 中获取比毫秒更为精确的时间(2012-07-03 11:54:33) 转载标签: 杂谈分类: 实践经验 from: http:/ 关键词: java 毫秒 微秒 纳秒 System.currentTimeMillis() 误差在对新写的超快 xml 解析器和 xpath 引擎进行效率测试时,为获取执行时间,开始也没多想就用了 System.currentTimeMillis() 来做的。由此碰到一个极其诡异的问题,同样的代码循环执行数次,分析每一次的执行时间,发现一大部分执行时间为小于 1 毫秒,但其间也发现有相当一部分的执行时间有非常大的跳跃,而且时间都近似 16 毫秒左右。这个

2、 1毫秒和 16 毫秒结果,以计算机的运行速度看,差距是惊人的,必须找出其原因。根据经验,在 16 毫秒时间内,cpu 可以运算的指令数量是相当惊人的,所以可以基本断定这 16ms 的差距,应当不是 cpu 在执行指令,另外因为测试过程中 gc 输出也已经打开,未见 gc 发生,所以怀疑可能是发生了什么 io 阻塞,比如文件读写、加载类库、或者什么网络操作等,由于笔者测试的系统的环境比较复杂,其间有用到 ehCache,数据库操作等,排查起来非常不容易。在困扰了好一阵之后,忽然想到可能计时系统有误差,这才翻回来查了下System.currentTimeMillis() 的文档,原来这个方法调用

3、了个 native 方法,获取的时间精度会依赖于操作系统的实现机制。奶奶的!既然不准,就看看有没更准的方法,在 jdk5 源码中,挨着 System.currentTimeMillis() 定义就是 System.nanoTime() 方法,靠,一下来了个精准 1000000 倍的取纳秒的方法,不过看 jdk 文档介绍,这个方法的精度依然依赖操作系统,不过再不准也能达到微秒级的准确度,放心用吧!结果测试结果一下准确了不少,没再发现比较大的跳跃了。所以这里提醒做非常精确的时间统计的朋友,谨慎使用 System.currentTimeMillis() 。虽然用取纳秒的方法解决了我的问题,但对于为何

4、使用 System.currentTimeMillis() 会造成那么大的跳跃,一直无解,有点郁闷。幸运的是今天恰巧看到一个网友做的测试很有意思,用事实数据证明了这个跳跃的存在,分享给感兴趣的同学!(原文链接:http:/ Java 中可以通过 System.currentTimeMillis()或者 System.nanoTime() (JDK=5.0) 方法获得当前的时间的精确值。但是通过阅读 Javadoc,我们发现这两个方法并不一定保证得到你所期望的精度。先来看 System.currentTimeMillis():Returns the current time in millise

5、conds. Note that while the unit of time of the return value is a millisecond, the granularity of the value depends on the underlying operating system and may be larger. For example, many operating systems measure time in units of tens of milliseconds.诚如上面所说返回值的粒度依赖于底层操作系统,那么它在不同的平台上到底能提供是么样的精度,是否像函数

6、名所写的那样真正 精确到 1 毫秒呢?看下面一段测试程序:public class ClockAccuracyTest public static void main(String args) SimpleDateFormat formatter = new SimpleDateFormat(dd-MMM-yyyy HH:mm:ss:SSS);int size = 4000000;/ create an array to hold millisecond times/ and loop to capture themlong times = new longsize;for (int i =

7、0; i deltas = new HashSet(); long delta = 0;long minDelta = Long.MAX_VALUE;long maxDelta = Long.MIN_VALUE;for (int i = 0; i time) delta = time - previousTime;deltas.add(delta);if (delta 0 & delta maxDelta) maxDelta = delta;System.out.print(raw=);System.out.print(time);System.out.print( | formatted=)

8、;System.out.print(formatter.format(new Date(time);System.out.print( | frequency=);System.out.print(count);System.out.print( | delta=); System.out.print(delta);System.out.println(ms);previousTime = time;time = timesi;count = 0; else count+;System.out.println();System.out.println(Minimum delta : + min

9、Delta + ms);System.out.println(Maximum delta : + maxDelta + ms);这段程序循环调用 System.currentTimeMillis()方法, 记录并显示结果,在我机器(Windows XP SP3)上运行输出如下:raw=1255659457187 | formatted=16-十月-2009 10:17:37:187 | frequency=147250 | delta=0msraw=1255659457203 | formatted=16-十月-2009 10:17:37:203 | frequency=447674 | de

10、lta=16msraw=1255659457218 | formatted=16-十月-2009 10:17:37:218 | frequency=436583 | delta=15msraw=1255659457234 | formatted=16-十月-2009 10:17:37:234 | frequency=439379 | delta=16msraw=1255659457250 | formatted=16-十月-2009 10:17:37:250 | frequency=426547 | delta=16msraw=1255659457265 | formatted=16-十月-2

11、009 10:17:37:265 | frequency=447048 | delta=15msraw=1255659457281 | formatted=16-十月-2009 10:17:37:281 | frequency=459522 | delta=16msraw=1255659457296 | formatted=16-十月-2009 10:17:37:296 | frequency=414816 | delta=15msraw=1255659457312 | formatted=16-十月-2009 10:17:37:312 | frequency=458826 | delta=1

12、6msMinimum delta : 15msMaximum delta : 16ms输出的四列从左到右分别是原始的毫秒值、格式化的时间、每个值循环的次数、与上一个不同值的差。可以看到在 Windows 上 System.currentTimeMillis()方法并不能提供 1ms 的计时粒度,它的粒度为 1516ms,从网上的其它文章来看,这个结果基本上是一致的,这也验证了 Javadoc 上所写的“ the granularity of the value depends on the underlying operating system and may be larger ”。在其他操

13、作系统,如 Linux、Solaris 上,我没有进行测试,但从网上的一些测试结果看, currentTimeMillis 方法在某些操作系统能够提供精确的 1 毫秒计时粒度。这是不是意味着 Java 在 Windows 上无法进行精确的毫秒计时了呢?当然不是,一种解决方案是采用 JNI 调用,利用 Windows 系统提供的函数计时;还有一个更简便的办法,就是使用 JDK5.0 加入的 System.nanoTime()方法。Javadoc 对该方法的描述如下:Returns the current value of the most precise available system tim

14、er, in nanoseconds.This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time. The value returned represents nanoseconds since some fixed but arbitrary time (perhaps in the future, so values may be negative). This method provides nanoseco

15、nd precision, but not necessarily nanosecond accuracy. No guarantees are made about how frequently values change. Differences in successive calls that span greater than approximately 292 years (263 nanoseconds) will not accurately compute elapsed time due to numerical overflow.它返回系统能够提供的最为精确的计时,以纳秒(10 亿分之一秒)为单位,但并不保证纳秒级精度。把上面的测试程序中黑体的一行改为“timesi = System.nanoTime();”,并把所有的“ms”该成 “ns”,循环次数改为 10。运行输出如下:raw=8705892679376 | formatted=17-十一月-2245 23:31:19:376 | frequency=1 | delta=0nsraw=8705892681053 | formatted=17-十一月-2245 23:31:21:053 | frequency=0 | delta=16

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 建筑/环境 > 综合/其它

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号