熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

用JNI實現一個高精度的Java計時器

2013-11-23 18:50:06  來源: Java核心技術 
    在Java程序中我們可以用SystemcurrentTimeMillis()來計時但是精度不高在我的機子(Pentium M GHz WinXP)上精度小於ms通過一個簡單的Java程序我們可以測試


public static void main(String[] args) {
        long begin = SystemcurrentTimeMillis();
        long current;
        while (begin == (current = SystemcurrentTimeMillis()))
            ;
        Systemoutprintln((current  begin) +  ms);
}
SystemcurrentTimeMillis()大約ms才變化一次

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

言歸正傳我們來講怎麼利用QueryPerformanceCounter來實現一個native的Java計時器

package cnpandaoentimer;

/**
 * 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 {
        SystemloadLibrary(extension);
        frequency = QueryPerformanceFrequency() / ;
    }
}

Native的代碼

#include cn_pandaoen_timer_Timerh
#include <windowsh>

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

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

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

下面我們來看看這個計時器都多高的精度

public class TimerTest {
    public static void main(String[] args) {
        long f = TimerQueryPerformanceFrequency();
        long p = TimerQueryPerformanceCounter();
        long c;
        while (p == (c = TimerQueryPerformanceCounter()))
            ;
        Systemoutprintln(((c  p) *  / f) +  ns);
    }
}
在同樣的系統下我得到ns的精度

這種方法的一個缺點當然是它現在還只能在Windows下使用如果有朋友願意幫忙實現別的系統下的native代碼的話我會非常感謝的
From:http://tw.wingwit.com/Article/program/Java/hx/201311/25828.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.