gr8vyguy@Blogjava

          用JNI實現高精度的Java計時器(Java Timer)

          在Java程序中,我們可以用System.currentTimeMillis()來計時,但是精度不高,在我的機子(Pentium M 1.5GHz, WinXP)上,精度小于10ms。通過一個簡單的Java程序,我們可以測試

          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的精度在很多情況下是不夠用的,比如開發射擊類游戲等等。而PC中自身計時器的精度要高很多,即使是WindowsXP提供的計時器也要比Java的System.currentTimeMillis()高太多了。比如用Win32的QueryPerformanceCounter函數,在我的機子上可以得到1ns的精度。計算機越發展,軟件利用硬件的程度和效率卻越來越差,這一點在Java的身上表現的尤其嚴重,隨著多核CPU的普及,這個問題還要進一步嚴重。

          言歸正傳,我們來講怎么利用QueryPerformanceCounter來實現一個native的Java計時器.
          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;
          }

          用法是,在開始點調用的timer.reset(), 結束時調用timer.getDuration()得到所用的時間,單位是ms.一個timer的instance可以多次使用.

          下面我們來看看這個計時器都多高的精度。
          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");
              }
          }
          在同樣的系統下,我得到1ns的精度.

          這種方法的一個缺點當然是,它現在還只能在Windows下使用,如果有朋友愿意幫忙實現別的系統下的native代碼的話,我會非常感謝的。

          代碼  timer.rar

          轉載請保留http://www.aygfsteel.com/xilaile/archive/2007/02/24/100441.html

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

          評論

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

          沒有cn_pandaoen_timer_Timer.h
          timer.rar的代碼下不下來,能否發到我的郵箱,多謝
          crazycowliu@sina.com  回復  更多評論   

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

          不好意思,才知道要用javah生成.h文件...  回復  更多評論   

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

          代碼結果是微秒級,不是納秒級。
          測試代碼
          f = Timer.QueryPerformanceFrequency();
          是每秒counter數,并不是毫秒。
          故乘1000000表示微秒,不是納秒。
            回復  更多評論   

          <2007年2月>
          28293031123
          45678910
          11121314151617
          18192021222324
          25262728123
          45678910

          導航

          統計

          公告

        1. 轉載請注明出處.
        2. msn: gr8vyguy at live.com
        3. 常用鏈接

          留言簿(9)

          隨筆分類(68)

          隨筆檔案(80)

          文章分類(1)

          My Open Source Projects

          搜索

          積分與排名

          最新評論

          主站蜘蛛池模板: 景洪市| 冕宁县| 海伦市| 邮箱| 光山县| 丽江市| 剑阁县| 绥中县| 民权县| 达拉特旗| 定结县| 仁寿县| 清水县| 百色市| 高碑店市| 宁城县| 广安市| 闸北区| 太保市| 揭东县| 乌恰县| 南陵县| 昭通市| 台安县| 荣成市| 普安县| 泗洪县| 梁平县| 略阳县| 拉萨市| 横山县| 武宣县| 随州市| 栾川县| 兰溪市| 富蕴县| 蕉岭县| 莒南县| 七台河市| 甘孜| 竹溪县|