gr8vyguy@Blogjava

          用JNI實(shí)現(xiàn)高精度的Java計(jì)時(shí)器(Java Timer)

          在Java程序中,我們可以用System.currentTimeMillis()來(lái)計(jì)時(shí),但是精度不高,在我的機(jī)子(Pentium M 1.5GHz, WinXP)上,精度小于10ms。通過一個(gè)簡(jiǎn)單的Java程序,我們可以測(cè)試

          public static void main(String[] args) {
                  long begin = System.currentTimeMillis();
                  
          long current;
                  
          while (begin == (current = System.currentTimeMillis()))
                      ;
                  System.out.println((current 
          - begin) + " ms");
          }

          System.currentTimeMillis()大約10ms才變化一次。

          10ms的精度在很多情況下是不夠用的,比如開發(fā)射擊類游戲等等。而PC中自身計(jì)時(shí)器的精度要高很多,即使是WindowsXP提供的計(jì)時(shí)器也要比Java的System.currentTimeMillis()高太多了。比如用Win32的QueryPerformanceCounter函數(shù),在我的機(jī)子上可以得到1ns的精度。計(jì)算機(jī)越發(fā)展,軟件利用硬件的程度和效率卻越來(lái)越差,這一點(diǎn)在Java的身上表現(xiàn)的尤其嚴(yán)重,隨著多核CPU的普及,這個(gè)問題還要進(jìn)一步嚴(yán)重。

          言歸正傳,我們來(lái)講怎么利用QueryPerformanceCounter來(lái)實(shí)現(xiàn)一個(gè)native的Java計(jì)時(shí)器.
          package cn.pandaoen.timer;

          /**
           * A Timer class uses native methods to measure times.
           *  
           * 
          @author pan
           
          */
          public class Timer {

              
          private long prev;

              
          public void reset() {
                  prev 
          = QueryPerformanceCounter();
              }

              
          /**
               * 
          @return the duration in ms from the point of reset()
               
          */
              
          public double getDuration() {
                  
          long current = QueryPerformanceCounter();
                  
          return (current - prev) / frequency;
              }

              
          static final double frequency;

              
          static native long QueryPerformanceFrequency();

              
          static native long QueryPerformanceCounter();

              
          static {
                  System.loadLibrary(
          "extension");
                  frequency 
          = QueryPerformanceFrequency() / 1000.0;
              }
          }

          Native的代碼
          #include "cn_pandaoen_timer_Timer.h"
          #include 
          <windows.h>

          JNIEXPORT jlong JNICALL
          Java_cn_pandaoen_timer_Timer_QueryPerformanceFrequency(JNIEnv 
          *e, jclass cls)
          {
              LARGE_INTEGER frequency;
              QueryPerformanceFrequency(
          &frequency);
              
          return (jlong)frequency.QuadPart;
          }

          JNIEXPORT jlong JNICALL
          Java_cn_pandaoen_timer_Timer_QueryPerformanceCounter(JNIEnv 
          *e, jclass cls)
          {
              LARGE_INTEGER counter;
              QueryPerformanceCounter(
          &counter);
              
          return (jlong)counter.QuadPart;
          }

          用法是,在開始點(diǎn)調(diào)用的timer.reset(), 結(jié)束時(shí)調(diào)用timer.getDuration()得到所用的時(shí)間,單位是ms.一個(gè)timer的instance可以多次使用.

          下面我們來(lái)看看這個(gè)計(jì)時(shí)器都多高的精度。
          public class TimerTest {
              
          public static void main(String[] args) {
                  
          long f = Timer.QueryPerformanceFrequency();
                  
          long p = Timer.QueryPerformanceCounter();
                  
          long c;
                  
          while (p == (c = Timer.QueryPerformanceCounter()))
                      ;
                  System.out.println(((c 
          - p) * 1000000 / f) + " ns");
              }
          }
          在同樣的系統(tǒng)下,我得到1ns的精度.

          這種方法的一個(gè)缺點(diǎn)當(dāng)然是,它現(xiàn)在還只能在Windows下使用,如果有朋友愿意幫忙實(shí)現(xiàn)別的系統(tǒng)下的native代碼的話,我會(huì)非常感謝的。

          代碼  timer.rar

          轉(zhuǎn)載請(qǐng)保留http://www.aygfsteel.com/xilaile/archive/2007/02/24/100441.html

          posted on 2007-02-23 22:49 gr8vyguy 閱讀(7857) 評(píng)論(3)  編輯  收藏 所屬分類: Java

          評(píng)論

          # re: 用JNI實(shí)現(xiàn)高精度的Java計(jì)時(shí)器(Java Timer)[未登錄] 2007-11-15 12:17 liu

          沒有cn_pandaoen_timer_Timer.h
          timer.rar的代碼下不下來(lái),能否發(fā)到我的郵箱,多謝
          crazycowliu@sina.com  回復(fù)  更多評(píng)論   

          # re: 用JNI實(shí)現(xiàn)高精度的Java計(jì)時(shí)器(Java Timer)[未登錄] 2007-11-15 12:46 liu

          不好意思,才知道要用javah生成.h文件...  回復(fù)  更多評(píng)論   

          # re: 用JNI實(shí)現(xiàn)高精度的Java計(jì)時(shí)器(Java Timer)[未登錄] 2013-07-30 17:19 Kent

          代碼結(jié)果是微秒級(jí),不是納秒級(jí)。
          測(cè)試代碼
          f = Timer.QueryPerformanceFrequency();
          是每秒counter數(shù),并不是毫秒。
          故乘1000000表示微秒,不是納秒。
            回復(fù)  更多評(píng)論   

          <2013年7月>
          30123456
          78910111213
          14151617181920
          21222324252627
          28293031123
          45678910

          導(dǎo)航

          統(tǒng)計(jì)

          公告

        1. 轉(zhuǎn)載請(qǐng)注明出處.
        2. msn: gr8vyguy at live.com
        3. 常用鏈接

          留言簿(9)

          隨筆分類(68)

          隨筆檔案(80)

          文章分類(1)

          My Open Source Projects

          搜索

          積分與排名

          最新評(píng)論

          主站蜘蛛池模板: 吉水县| 桂林市| 定州市| 弥勒县| 若尔盖县| 鄂托克旗| 大足县| 昌乐县| 威信县| 嘉黎县| 天长市| 天等县| 恭城| 昌乐县| 罗甸县| 新和县| 襄汾县| 阜平县| 元氏县| 多伦县| 崇文区| 交口县| 阿坝| 桃江县| 枝江市| 扎鲁特旗| 静宁县| 灌阳县| 旌德县| 格尔木市| 大渡口区| 龙泉市| 剑河县| 厦门市| 汉源县| 扎赉特旗| 潮安县| 墨脱县| 宾川县| 大名县| 乌兰浩特市|