Skip to main content
GameDev.net gamedev.net
🔒 Locked

[java] Thread.sleep

Started by FiveFootFreak Jan 29, 2005 at 6:03 AM 7 replies 2.1k views
Original Post
FiveFootFreak
FiveFootFreak
Greetings, this is my very typical game loop (simplified):

        while(running){
	    	startOfLoop = System.currentTimeMillis();
	    	
	    	gameLogic();		
	    	updateGraphics();
	    	
	    	endOfLoop = System.currentTimeMillis();
	    	
	    	loopTime = endOfLoop - startOfLoop;
	    	
	    	while (loopTime < 50){
	    	    try { Thread.sleep(5); } catch (Exception e) {}
	    	    loopTime += 5;
	    	}
        }
As you can see, I'm aiming for 20fps. That's why the inner while-statement checks to see if the looptime is lower than 50ms. If it is, the threads sleeps for 5ms and 5ms are added to the counter, until it's over 50. After experimenting with different sleep values I found that using high values above 20 made the application eat upto 90% of total CPU cycles (I looked it up in the task manager). At 10, this slumped to about 30% and at 5 it's about 15%. I was wondering, why is it, that higher precision requires less CPU time? Is there a way to calculate an ideal value for sleep()? Or should you always use Thread.sleep(1)? I felt uncomfortable with that, thats why I left it at 5. What actually happens inside Thread.sleep()?
Thygrrr
Thygrrr
You should use Thread.yield() instead.

That way, you get the best performance possible. Thread.sleep(int) has no guarantee that it will return after the gifen time; it only guarantees that it won't be back earlier.

Thread.sleep(int) is for simple, occasional, long time waiting jobs, for example once every 250ms. As soon as "real-time" issues, such as your frame rate, are dependent on the waiting time of your thread, use Thread.yield() instead, and either use the extra time you saved for extra frames (and thus, more smoothness), or quickly check whether enough time has passed, and if not - Thread.yield() again.

A big difference between Thread.yield() and Thread.sleep(int) is that a sleeping thread can be interrupted, raising an InterruptedException. A yielding thread doesn't need to be interrupted, as execution would be resumed ASAP anyway!


Thread.sleep(int) and Thread.yield() both are function calls into the thread management system, where they will simply "draw a number and wait". There are countless implementation-specific details to this, involving spin counts, mutices, and other things that can cause your thread or other threads to wait; and developing a multi-threading system (e.g. the code that makes up "class Thread") is a science all by itself.

capn_midnight
capn_midnight
instead of trying to slow down the thread, why not just do things when you want it to happen, instead? Check out javax.swing.Timer.
FiveFootFreak
FiveFootFreak
Thanks for the replies, I'll check into Thread.yield() and into Timer to see what suits me best.
FiveFootFreak
FiveFootFreak
@Thygrrr
Thread.yield() takes no parameters and doesn't return a value, so how do I know how long it yields? Do I need to surround it with calls to System.currentTimeMillis(), like with gameLogic() and updateGraphics(), to see if sufficient time has ellapsed to continue, or is there a "smarter" way of using it?
Raghar
Raghar
Nanosecond precision is better, and delta is even more better.
So it's either Thread.yield(), or Thread.sleep(20)
Differents OSs have different minimal sleep periode, so you might experience funny results.
Thygrrr
Thygrrr
Quote:
Original post by FiveFootFreak
@Thygrrr
Thread.yield() takes no parameters and doesn't return a value, so how do I know how long it yields? Do I need to surround it with calls to System.currentTimeMillis(), like with gameLogic() and updateGraphics(), to see if sufficient time has ellapsed to continue, or is there a "smarter" way of using it?


Yes, you need to surround it with those calls to determing how long your thread was sleeping. This gives you control on the millisecond level, which is usually enough precision for games.
Malderi
Malderi
This might be an issue specific to the UNIX computers I played with for a while, but Thread.sleep(x) where x<5 didn't do anything. I'm pretty sure that's a precision issue, where if it's less than 5 milliseconds, something considers that to be useless and doesn't sleep. I've never had any real problems with it, but it's still not something that I use regularly, so take that with a grain of salt =)
H_o_p_s
H_o_p_s
Quote:
Original post by FiveFootFreak
	    	while (loopTime < 50){	    	    try { Thread.sleep(5); } catch (Exception e) {}	    	    loopTime += 5;	    	}


Why not just use something like:
[source: java]	public void main_loop(int w) {		WAIT = w;		long START_TIME = 0;		long TOTAL_TIME = 0;		long MILL = 0;		long MILL_WAIT = 0;				while (!done) {			START_TIME = System.currentTimeMillis();			MILL = 1000/WAIT;						update(MILL); //Update our objects, with the given ms						if (System.currentTimeMillis() - START_TIME < MILL) {				drawScreen(); //Draws our objects			}						TOTAL_TIME = System.currentTimeMillis() - START_TIME;			MILL_WAIT = (MILL - TOTAL_TIME);			if (TOTAL_TIME < MILL) {				if (MILL_WAIT > 0) {					try {						Thread.sleep(MILL_WAIT);					} catch (InterruptedException e) {}				}			}		}		System.exit(0);	}WAIT (or w) is how many FPS you wantSTART_TIME is the currentTimeMillis() at the start of the loopMILL is how many ms to wait to get the given FPSTOTAL_TIME is how long in ms to draw the screenMILL_WAIT is how long to Thread.sleep() to get the FPS


Basically you do a this.main_loop(20); to get a 20FPS
And this way the Thread doesn't wake up every 5ms to see if it should sleep again.
BRING BACK THE BLACK (or at least something darker)

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.