




已阅读5页,还剩2页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
java中获取比毫秒更为精确的时间(2012-07-03 11:54:33) 转载标签: 杂谈分类: 实践经验 from: /paul_lh/article/details/6419982 关键词: java 毫秒 微秒 纳秒 System.currentTimeMillis() 误差在对新写的超快xml解析器和xpath引擎进行效率测试时,为获取执行时间,开始也没多想就用了System.currentTimeMillis() 来做的。由此碰到一个极其诡异的问题,同样的代码循环执行数次,分析每一次的执行时间,发现一大部分执行时间为小于1毫秒,但其间也发现有相当一部分的执行时间有非常大的跳跃,而且时间都近似16毫秒左右。这个1毫秒和16毫秒结果,以计算机的运行速度看,差距是惊人的,必须找出其原因。根据经验,在16毫秒时间内,cpu可以运算的指令数量是相当惊人的,所以可以基本断定这16ms的差距,应当不是cpu在执行指令,另外因为测试过程中gc输出也已经打开,未见gc发生,所以怀疑可能是发生了什么io阻塞,比如文件读写、加载类库、或者什么网络操作等,由于笔者测试的系统的环境比较复杂,其间有用到ehCache,数据库操作等,排查起来非常不容易。在困扰了好一阵之后,忽然想到可能计时系统有误差,这才翻回来查了下System.currentTimeMillis() 的文档,原来这个方法调用了个native方法,获取的时间精度会依赖于操作系统的实现机制。奶奶的!既然不准,就看看有没更准的方法,在jdk5源码中,挨着System.currentTimeMillis() 定义就是System.nanoTime() 方法,靠,一下来了个精准1000000倍的取纳秒的方法,不过看jdk文档介绍,这个方法的精度依然依赖操作系统,不过再不准也能达到微秒级的准确度,放心用吧!结果测试结果一下准确了不少,没再发现比较大的跳跃了。所以这里提醒做非常精确的时间统计的朋友,谨慎使用System.currentTimeMillis() 。虽然用取纳秒的方法解决了我的问题,但对于为何使用System.currentTimeMillis() 会造成那么大的跳跃,一直无解,有点郁闷。幸运的是今天恰巧看到一个网友做的测试很有意思,用事实数据证明了这个跳跃的存在,分享给感兴趣的同学!(原文链接:/elky1982/archive/2009/10/16/4677365.aspx)以下内容为转帖:在Java中可以通过System.currentTimeMillis()或者System.nanoTime() (JDK=5.0) 方法获得当前的时间的精确值。但是通过阅读Javadoc,我们发现这两个方法并不一定保证得到你所期望的精度。先来看System.currentTimeMillis():Returns the current time in milliseconds. 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.诚如上面所说返回值的粒度依赖于底层操作系统,那么它在不同的平台上到底能提供是么样的精度,是否像函数名所写的那样真正 精确到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 them long times = new longsize; for (int i = 0; i size; i+) timesi = System.currentTimeMillis(); / now display the unique times long time = times0; long previousTime = times0; long count = 0; Set 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=); 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 : + minDelta + 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 | delta=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-十月-2009 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=16msMinimum 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 ”。在其他操作系统,如Linux、Solaris上,我没有进行测试,但从网上的一些测试结果看, currentTimeMillis方法在某些操作系统能够提供精确的1毫秒计时粒度。这是不是意味着Java在Windows上无法进行精确的毫秒计时了呢?当然不是,一种解决方案是采用JNI调用,利用Windows系统提供的函数计时;还有一个更简便的办法,就是使用JDK5.0加入的System.nanoTime()方法。Javadoc对该方法的描述如下:Returns the current value of the most precise available system timer, 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 nanosecond 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=1677nsraw=8705892682449 | formatted=17-十一月-2245 23:31:22:449 | frequency=0 | delta=1396nsraw=8705892683846 | formatted=17-十一月-2245 23:31:23:846 | frequency=0 | delta=1397nsraw=8705892685522 | formatted=17-十一月-2245 23:31:25:522 | frequency=0 | delta=1676nsraw=8705892686919 | formatted=17-十一月-2245 23:31:26:919 | frequency=0 | delta=1397nsraw=8705892688316 | formatted=17-十一月-2245 23:31:28:316 | frequency=0 | delta=1397nsraw=8705892689713 | formatted=17-十一月-2245 23:31:29:713 | frequency=0 | delta=1397nsraw=8705892691110 | formatted=17-十一月-2245 23:31:31:110 | frequency=0 | delta=1397nsMinimum delta : 1396nsMaximum delta : 1676ns我们看到frequency=0,这意味着每执行一次循环,nanoTime方法的返回值都发生了改变,改变的差值平均大约为1467ns(不同性能的机器结果会不同)。这说明nanoTime方法计时的精度是非常高的,粒度比方法本身的调用执行耗时还要小。回到上面的问题,如何在windows上实现精确的毫秒计时呢。答案就是用“System.nanoTime()/1000000L”代替“System.currentTimeInMills()”。把测试程序黑体的一行代码改为timesi = System.nanoTime()/1000000L;,循环次数5000,运行输出结果如下:raw=9487129 | formatted=01-一月-1970 10:38:07:129 | frequency=202 | delta=0msraw=9487130 | formatted=01-一月-1970 10:38:07:130 | frequency=704 | delta=
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 加强课件进行教学设计
- 2025年物业行业入门指南初级面试模拟题及答案详解
- 全国防灾减灾日教育班会
- 3D打印技术在纺织行业应用研究
- 入冬时如何保护呼吸道健康
- 幼儿园国庆节策划方案5
- 甲状腺手术课件
- 制作电梯的教学课件
- 甲午海战失败原因
- 不规则图形面积教学课件
- 企业资产收购尽职调查操作手册
- 2025年陕西省综合评标评审专家库考试历年参考题库含答案详解(5套)
- 软件开发项目进展汇报
- 康复理疗室感染管理要求
- 六安市辅警真题2024
- 心电监护技术操作并发症的预防与处理
- 海南省省直辖县级行政单位2024-2025学年七年级下学期7月期末考试语文试卷(含答案)
- 2025年《资料员》考试题库附答案【模拟题】
- 磷石膏砌块项目可行性研究报告
- Unit 8 Let's Communicate!Section A(1a-1d)同步练习(含答案)2025-2026学年人教版(2024)八年级英语上册
- 现场调试合同协议书模板
评论
0/150
提交评论