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

          搜索

          積分與排名

          最新評論

          主站蜘蛛池模板: 凌海市| 阜康市| 渑池县| 定远县| 乌鲁木齐县| 安吉县| 凤山市| 太仆寺旗| 鹰潭市| 太康县| 罗源县| 大英县| 义乌市| 昭苏县| 西林县| 美姑县| 敖汉旗| 丹寨县| 朝阳市| 工布江达县| 济南市| 宜春市| 弥渡县| 邹城市| 定结县| 顺平县| 宁德市| 河北区| 锡林郭勒盟| 泸州市| 台中县| 浦东新区| 宜昌市| 高陵县| 达州市| 南宁市| 钟祥市| 济源市| 东丰县| 庆阳市| 合作市|