我分别用System.naoTime()函数和System.currentTimeMillis()函数来获得系统时间来进行sleep(100)的误差计算,的到的结果大不一样。有没有人能告诉为什么用前者计算出的系统时间却比后者的误差要少的多呢???
下面是我的代码:
先用naoTime
public void testWait(){
for(int i = 0; i < 100; i ++) {
long time1 = System.nanoTime();
try {
Thread.sleep(100);} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println((System.nanoTime()- time1)/1000000.0);
}
}
=====================一下是执行结果=====================
100.144895
99.933042
100.460098
100.474048
100.588389
100.38071
100.471397
100.29281
100.473707
100.475345
100.454874
===================================
误差居然在1个毫秒之内!!神奇啊!!!
然后,偶改用System.currentTimeMillis()
public void testWait(){
for(int i = 0; i < 100; i ++) {
long time1 = System.currentTimeMillis();
try {
Thread.sleep(100);} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println((System.currentTimeMillis()- time1));
}
}
==============一下是结果============
109
94
109
94
109
94
94
109
94
109
94
109
94
94
=====================
误差居然是10毫秒以内,天哪!!这个差别也太大了吧!! 

解决方案 »

  1.   

    Windows 系统的计时精度只有 40ms,10ms 忽略不计!
      

  2.   

    上面说错了,Windows 的计时精度是 10ms,不是 40ms,因此 10ms 在偏差范围之内。System.currentTimeMillis();
    在 Windows 平台上的 JDK 实现是采用 windows.h 函数 GetSystemTimeAsFileTime 实现的
    GetSystemTimeAsFileTime API: http://msdn.microsoft.com/en-us/library/ms724397%28VS.85%29.aspx
    据悉这个时间的精度在 10ms 左右。System.nanoTime();
    在 Windows 平台上是使用 QueryPerformanceCounter 和 QueryPerformanceFrequency 这两个函数实现的据称 Windows 平台上这两种方式都有一定的缺陷。根据 System.currentTimeMillis() 和 System.nanoTime() 两个方法在 Windows 平台上的本地代码,我写了个这两个方法内部具体是怎么工作的。程序运行后会在屏幕上输出与 JDK 那两个函数相同的 nano 和 millis 值: #include <windows.h>
    #include <iostream>#define NANOS_PER_SEC       1000000000typedef __int32             jint;
    typedef __int64             jlong;
    typedef unsigned __int32    juint;
    typedef unsigned __int64    julong;using namespace std;static jlong    _calculated_offset       = 0;
    static int      _has_calculated_offset   = 0;static void set_low(jlong* value, jint low) {
        *value &= (jlong)0xffffffff << 32;
        *value |= (jlong)(julong)(juint)low;
    }static void set_high(jlong* value, jint high) {
        *value &= (jlong)(julong)(juint)0xffffffff;
        *value |= (jlong)high << 32;
    }static jlong jlong_from(jint h, jint l) {
        jlong result = 0;
        set_high(&result, h);
        set_low(&result,  l);
        return result;
    }jlong as_long(LARGE_INTEGER x) {
        jlong result = 0;
        set_high(&result, x.HighPart);
        set_low(&result,  x.LowPart);
        return result;
    }jlong offset() {
        if (_has_calculated_offset) return _calculated_offset;
        SYSTEMTIME java_origin;
        java_origin.wYear          = 1970;
        java_origin.wMonth         = 1; 
        java_origin.wDayOfWeek     = 0; // ignored 
        java_origin.wDay           = 1; 
        java_origin.wHour          = 0; 
        java_origin.wMinute        = 0; 
        java_origin.wSecond        = 0; 
        java_origin.wMilliseconds  = 0; 
        FILETIME jot;
        SystemTimeToFileTime(&java_origin, &jot);
        _calculated_offset = jlong_from(jot.dwHighDateTime, jot.dwLowDateTime);
        _has_calculated_offset = 1;
        return _calculated_offset;
    }jlong windows_to_java_time(FILETIME wt) {
        jlong a = jlong_from(wt.dwHighDateTime, wt.dwLowDateTime);
        return (a - offset()) / 10000;
    }int main () {    LARGE_INTEGER current_count, frequence;    QueryPerformanceCounter(&current_count);
        QueryPerformanceFrequency(&frequence);
      
        jlong j_current_count = as_long(current_count);
        jlong j_frequence     = as_long(frequence);
      
        cout << "nano: " << (jlong)((double)j_current_count / (double)j_frequence * NANOS_PER_SEC) << endl;    FILETIME ft;
        GetSystemTimeAsFileTime(&ft);
        cout << "millis: " << windows_to_java_time(ft) << endl;
        getchar();
        return 0;
    }