Java Thread.sleep Exception
I've made a class that controls the speed at which my program runs, kind of like a vertical sync, and it passes some necessary information to the program at each frame. I have the entire thing working, but I've tried using the more accurate Thread.sleep(long millis, int nanos), something I'm fairly inexperienced using. Based upon the descriptions I've seen, it simply adds the milliseconds provided to the nanoseconds, then pauses the thread. But, about 90% of the frames throw an odd exception, which I really cannot decipher.
java.lang.IllegalArgumentException: nanosecond timeout value out of range
The following is most of the code I used, that interacts in any way with the variable I use to delay the thread.
long startTime = System.nanoTime();
w开发者_如何学JAVAhile (! this.stop)
{
try
{
// Run Frame
long endTime, deltaTime, deltaRemainder;
endTime = System.nanoTime();
deltaTime = endTime - startTime;
deltaRemainder = this.rate - (deltaTime % this.rate);
System.out.println("Frame Completed with "
+ (double)(deltaRemainder * .000000001) + " seconds left!");
if (deltaRemainder > 0)
Thread.sleep(0, (int)(deltaRemainder));
startTime = System.nanoTime();
}
catch (Exception e)
{
e.printStackTrace();
}
}
rate is the variable which is equal to the length of a frame in nanoseconds, stop is really unimportant, and apparent. start/endTime are the times at the start and end of a frame. deltaTime is the length of time the frame took to finish. And finally, deltaRemainder is the amount of extra time the frame should have taken to finish(if it takes longer than it should, it jumps up to end at the next possible frame).
Could anyone explain why this exception is thrown? I would really prefer to use the accuracy this function provides.
It seems that your deltaRemainder is outside of the allowed ranged between 0 and 999999.
From Thread.sleep documentation:
- millis - the length of time to sleep in milliseconds.
- nanos - 0-999999 additional nanoseconds to sleep.
So you should check if it is greater than 999999 and if so, put the value that is above 999999 into milliseconds, e.g.
int milliseconds = 0;
if ( deltaRemainder > 999999 ) {
milliseconds = deltaRemainder / 1000000;
deltaRemainder = deltaRemainder % 1000000;
}
if ( milliseocnds > 0 || deltaRemainder > 0) {
Thread.sleep(milliseconds, deltaRemainder);
}
Edit: My sample code is to be treated as "late night code", there are bugs in it ;).
Only a guess:
ints have 32bits so ints go from -2^31 to 2^31-1 If the deltaRemainder is too big it can overflow and the resulting int will be negative. Can your deltaRemainder go over 2^31? (2GB which is aprox 2.000.000.000, it is: 2 secs?)
Other guess is:
deltaRemainder is > 0 but < 1. So the int'ed value is 0.
精彩评论