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

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

] 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 long[size];

for (int i = 0; i < size; i++) {

times[i] = System.currentTimeMillis();

}

// now display the unique times

long time = times[0];

long previousTime = times[0];

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 < size; i++) {

if (times[i] > time) {

delta = time - previousTime;

deltas.add(delta);

if (delta > 0 && delta < minDelta) {

minDelta = delta;

} else if (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=");

相关文档
最新文档