在java程序中,我们可以用system.currenttimemillis()来计时,但是精度不高,在我的机子(pentium m 1.5ghz, winxp)上,精度小于10ms。通过一个简单的java程序,我们可以测试
code highlighting produced by actipro codehighlighter (freeware)
http://www.codehighlighter.com/
-->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计时器.
code highlighting produced by actipro codehighlighter (freeware)
http://www.codehighlighter.com/
-->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的代码
code highlighting produced by actipro codehighlighter (freeware)
http://www.codehighlighter.com/
-->#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可以多次使用.
下面我们来看看这个计时器都多高的精度。
code highlighting produced by actipro codehighlighter (freeware)
http://www.codehighlighter.com/
-->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代码的话,我会非常感谢的。
code highlighting produced by actipro codehighlighter (freeware)
http://www.codehighlighter.com/
-->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计时器.
code highlighting produced by actipro codehighlighter (freeware)
http://www.codehighlighter.com/
-->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的代码
code highlighting produced by actipro codehighlighter (freeware)
http://www.codehighlighter.com/
-->#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可以多次使用.
下面我们来看看这个计时器都多高的精度。
code highlighting produced by actipro codehighlighter (freeware)
http://www.codehighlighter.com/
-->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");
}
}
这种方法的一个缺点当然是,它现在还只能在windows下使用,如果有朋友愿意帮忙实现别的系统下的native代码的话,我会非常感谢的。
闽公网安备 35060202000074号