I'd like to create MIDI clock which works basically like a normal clock. It simply ticks and counts its ticks. Now I have read quite a few times that Thread.sleep() isn't accurate at all. So correcting it every every few cycles ensures that it is stable in the long term?
My Clock Class
public class Clock implements Runnable {
long beatsPassed = 0;
double bpm = 120; // default
double beatLength; // default
boolean running = false;
Clock(int bpm) {
this.bpm = bpm;
this.beatLength = 60.0 / bpm;
this.running = true;
}
public void run() {
int beatLengthInMS = (int) (this.beatLength * 1000);
long baseTime = System.currentTimeMillis();
// long corrected = 1;
try {
while (running) {
// check delay every 9 beats
// mod == 0 lets it the first time through which causes a negative timeout
if (this.beatsPassed % 10 == 9) {
// corrected = (System.currentTimeMillis() - baseTime) - (beatLengthInMS * 9);
Thread.sleep(beatLengthInMS + ((System.currentTimeMillis() - baseTime) - (beatLengthInMS * 9)));
baseTime = System.currentTimeMillis();
} else {
Thread.sleep(beatLengthInMS);
}
this.beatsPassed++;
// System.out.println(corrected);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Now I have measured actually quite steady times. It always adds about 6-9ms.
Am I forgetting something fundamental or is my approach wrong? Also great would be if you could tell me a more performant way to this?
The simplest approach (apart from using Timer, there are AFAIK two of them in the JDK) is a method
void sleepUntil(long absoluteTime) throw InterruptedException {
while (true) {
long now = System.currentTimeMillis();
if (now >= absoluteTime) break;
Thread.sleep(absoluteTime - now);
}
}
The loop is used because of spurious wakeups (which may never occur in practice, but better safe than sorry). The absoluteTime gets computed in advance (basically, you only look at the current time at the very beginning).
Related
In my platforming game, I have a swing timer that ticks the following method every 17 milliseconds. It is here that I run the various events that I need to run. My plan was to sleep the timer for 1 second whenever the player died.
My problem is that I don't really have a firm understanding of how to sleep a swing timer. Every example that I look at involves using a Thread which is not what I am doing. When I do the following I get a IllegalMonitorStateException error.
public void actionPerformed(ActionEvent e)
{
if (!louis.isDead)
{
if (louis.right)
{
louis.moveR();
}
if (louis.left)
{
louis.moveL();
}
if (!louis.left && !louis.right)
louis.friction();
louis.gravity();
louis.checkCol(charMap, mapX, mapY);
mapX -= louis.moveX();
mapY -= louis.moveY();
louis.checkDeath(charMap, mapX, mapY);
}
else
{
try {
time.wait(1000);
} catch (InterruptedException e1) {e1.printStackTrace();}
mapX = initMapX;
mapY = initMapY;
louis = new Player(spawnX, spawnY);
}
repaint();
}
Thanks in advance
My problem is that I don't really have a firm understanding of how to sleep a swing timer.
You don't. You don't sleep anything in Swing, not unless you want to put your entire GUI asleep. Instead why not simply record the start time, check the elapsed time with each tick, and then activate whatever code you want activated when the elapsed time is greater than your cut-off?
Not sure what you're trying to do, but perhaps something in this sort of range (code not tested)
private static final long TOTAL_DEATH_TIME = 1000L; // total time of your delay
private long deathInitTime = -1L; // start time of death throes
public void actionPerformed(ActionEvent e) {
if (!louis.isDead) {
// .... etc... unchanged from your code
} else {
// he's dead
if (deathInitTime < 0) {
// if dead but just now dead, initialize deathInitTime
deathInitTime = System.currentTimeMillis();
} else {
// he's been dead
// check how long he's been dead
long deathTime = System.currentTimeMillis() - deathInitTime;
if (deathTime > TOTAL_DEATH_TIME) {
// if he's been dead long enough, call this code
mapX = initMapX;
mapY = initMapY;
louis = new Player(spawnX, spawnY);
deathInitTime = -1L; // and re-initialize deathInitTime
}
}
}
repaint();
}
I have many bitmaps I move around on a surfaceview and sometimes the fps drops which makes the bitmap move slow or super fast randomly, I've seen someone post a solution using system time or something like that, but couldn't find it, so I wonder if anyone knows how can I make the speed be the same even if the fps drops.
Edit:
I thought that maybe I can calculate time different using:
int myFPS;
if(gameLoopThread.startTime!=System.currentTimeMillis())
myFPS=(int) (1000 / (gameLoopThread.startTime-System.currentTimeMillis())*-1);
else
myFPS=25;
float new2=1;
new2=25/myFPS;
and then just multiple
currentSpeed.y += speed*new2;
but it didn't work out because the fps showed was wrong, but I think this is the way to do it? or I might be wrong..
Update:
Single threaded loop:
To keep the speed of your game at a constant rate, you will have to skip rendering at some point, should a loop iteration take longer than expected.
while(isRunning){
beginTime = SystemClock.uptimeMillis();
framesSkipped = 0;
//Update game state
update();
render();
//how long we took to update and render
loopTime = SystemClock.uptimeMillis() - beginTime;
//calculate how long to sleep
sleepTime = loopPeriod - timeDiff;
//All work was done on time.
if (sleepTime > 0) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {}
}
//We were too slow. Update without rendering.
while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
update();
//make sure we don't keep looping here.
sleepTime += loopPeriod;
framesSkipped++;
}
}
}
This loop prioritizes your logic updates, and skips rendering if we are behind. The benefit is, that your game-actors are updated constantly and independently from possible frame rate drops.
Two threads: (original answer)
Another way to ensure steady movement at low FPS, is to do rendering in one thread, and logical stuff in another one.
Example for the game logic thread:
while(isRunning){
startTime = SystemClock.uptimeMillis();
//update game logic, no rendering.
update();
//time it took to update the game state.
loopTime = SystemClock.uptimeMillis() - startTime;
//pausing here to make sure we update the right amount per second.
if(loopTime < updatePeriod){
try {
Thread.sleep(updatePeriod-updateTime);
} catch (InterruptedException e) {
Log.e(TAG,"Interrupted while sleeping");
}
}
}
The update period is the amount of milliseconds a single update iteration is allowed to take.
updatePeriod = 1000 / ups;
ups = updates per second. If your game runs at 60 fps max, use 60 ups.
Note that both loops are very basic, and, without modification, not suitable for advanced applications.
Also, use SystemClock.uptimeMillis(); it's more reliable.
How I kept track of fps 1000milliseconds / 25 = 40 fps
At the start of the while loop make sure you get the time.
long starttime = System.currentTimeMillis();
Then after everything is finished and rendered you get the time again.
long endtime = System.currentTimeMillis();
Subtract start time from end time then divide by 1000 multiply by -1 to get how many times your runnable can loop in a second.
int MyFPS = (int) (1000 / (starttime - endtime) * -1);
If your answer is 75 then you're running at 75fps.
You just need to put the thread to sleep for 35 milliseconds to be at 40fps.
Tracking the low fps I never got around to doing. Hope this helps a little though.
#Override
public void run() {
while (THREAD) {
long starttime = System.currentTimeMillis();
if (!myHolder.getSurface().isValid())
continue;
Update(); <----Running the game.
Main_Render(); <----Rendering graphics.
long endtime = System.currentTimeMillis();
int MyFPS = (int) (1000 / (starttime - endtime) * -1);
if (MyFPS >= 25) {
sleep_length = MyFPS - 25;
try {
Thread.sleep(sleep_length);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
I use the following loop (cut some stuff out) as the main loop for a game, but I can't get it to throttle down to a speed I want it to, it keeps running about twice as fast as I intend.
private void myLoop() throws InterruptedException {
long timer = TimeUtils.getMillis();
int achievedLoops = 0;
long currTime = 0l;
long loopTime = 0l;
long lastTime = TimeUtils.getNano();
while(!isRequestedToStop) {
currTime = TimeUtils.getNano();
loopTime = currTime - lastTime;
lastTime = currTime;
if(TimeUtils.getDeltaMillis(timer) > 1000) {
timer += 1000;
logger.debug(achievedLoops + " Loops");
achievedLoops = 0;
}
achievedLoops++;
if(loopTime < TIME_PER_LOOP) {
Thread.sleep( (TIME_PER_LOOP - loopTime) / 1000000l);
}
}
}
Alternative implementation of the sleeping, gets slightly better results (loop runs only 1.9 times too often):
while(loopTime < TIME_PER_LOOP) {
Thread.sleep(1l);
loopTime += 1000000l;
}
Another alternative:
while(loopTime < TIME_PER_LOOP) {
Thread.sleep(1l);
loopTime = TimeUtils.getNano() - lastTime;
}
Why does that happen?
Are there any other ways to throttle a thread down?
I basically could run it uncontrolled as the logic is tied to timed steps, but I would like to reduce the total runs of the loop as otherwise there's a marginal chance of it doing damage to a CPU..
LockSupport can disable the scheduling of a thread for a specified number of nanoseconds.
LockSupport.parkNanos(TIME_PER_LOOP - loopTime);
But as others have mentioned there are better ways to control timing (e.g. ScheduledExecutorService).
Each time you perform the division
(TIME_PER_LOOP - loopTime) / 1000000l
You are truncating the result and sleeping up to 1ms less than you expect (average 0.5ms). Given your 4ms loop time, this would easily cause your loop to run twice as fast as you expect. As others have mentioned, there are much better ways to control timing.
Am creating a program that is based on mixing and making perturbation in a population containing solutions Vector.
So I created a for loop that stops after a certain time given by the user.
Inside the loop, am going to call 5 procedures and I thought that if i put each procedure in a thread will make the program making more solutions in a same time than calling normal methods.
Here 5 created the 5 threads, but when i start them the don't want to stop even if i use the Thread.stop, Thread.suspend, Thread.interrupt or Thread.destroy
Here is my code and could u help me with your ideas ?
I have inserted a new variable :
public volatile boolean CrossOpb = true;`
Here is my code:
Thread CrossOp = new Thread(new Runnable() {
public void run() {
while(CrossOpb == true){
int rdmCross2=(int) (Math.random() * allPopulation.size()) ; // Crossover 1st vector
int rdmCross1=(int) (Math.random() * allPopulation.size()) ;
Vector muted = new Vector();
Vector copy = copi((Vector) allPopulation.get(rdmCross2));
Vector callp = copi((Vector) allPopulation.get(rdmCross1));
muted = crossover(callp, copy);
System.out.println("cross over Between two Randoms ----------->");
affiche_resultat(muted);
allPopulation.add(muted);
}
}
});
The loop :
CrossOp.setDaemon(true);
int loop = 1;
long StartTime = System.currentTimeMillis() / 1000;
for (int i = 0; i < loop; ++i) {
loop++;
if (timevalue < ((System.currentTimeMillis() / 1000) - StartTime)) {
loop = 0;
CrossOpb = false;
}
CrossOp.start();
}
I already answered to a similar question. In that case, it was C#, but the concept is the same.
You must not kill threads. Threads must exit on their own will.
Just put a volatile boolean variable somewhere, and set it to true/false, when you want your thread to terminate, then, in the thread, replace the while (true) with a while (myVariable == true/false).
Anyway, you say:
Inside the loop, am going to call 5 procedures ant i thought that if i put each procedure in a thread will make the program making more solutions in a same time than calling normal methods.
Well, that's generally false. If the procedures are data-dependent (each of them depends on the results of the previous one), putting them on threads will change nothing. It might be smarter to put iterations in a pipeline, so that you have 5 threads executing steps of successive iterations. I'm not sure if that's possible for genetic algorithms, and anyway you'll have to handle some special case (e.g. a mutation, that alters the population of partially computed iterations).
How to run a Thread for a specific amount of time:
Here is the basic approach is to keep calculate how long the Thread has run and exit and return the result, which in our case here is details on how long the Thread executed.
NOTE: you must use System.nanoTime() as System.currentTimeMillis() will just return the same thing every time you call it in the method.
I use a Random number to calculate different lifetimes for each of the Callables so that you can see that they don't execute exactly for the time specified but they are very very close, and the variance of the delta is pretty consistent, at least on my machine.
Here a Gist of the code below for easier access.
package com.stackoverflow.Q18818482;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;
public class Question18818482
{
public static Random RND;
static
{
RND = new Random();
}
public static void main(final String[] args)
{
try
{
final ExecutorService es = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
final List<Future<String>> results = new ArrayList<>(10);
for (int i = 0; i < 10; i++)
{
results.add(es.submit(new TimeSliceTask(RND.nextInt(10), TimeUnit.SECONDS)));
}
es.shutdown();
while(!results.isEmpty())
{
final Iterator<Future<String>> i = results.iterator();
while (i.hasNext())
{
final Future<String> f = i.next();
if (f.isDone())
{
System.out.println(f.get());
i.remove();
}
}
}
}
catch (InterruptedException e)
{
throw new RuntimeException(e);
}
catch (ExecutionException e)
{
throw new RuntimeException(e);
}
}
public static class TimeSliceTask implements Callable<String>
{
private final long timeToLive;
private final long duration;
public TimeSliceTask(final long timeToLive, final TimeUnit timeUnit)
{
this.timeToLive = System.nanoTime() + timeUnit.toNanos(timeToLive);
this.duration = timeUnit.toMillis(timeToLive);
}
#Override
public String call() throws Exception
{
while( timeToLive <= System.nanoTime() )
{
// simulate work here
Thread.sleep(500);
}
final long end = System.nanoTime();
return String.format("Finished Elapsed Time = %d, scheduled for %d", TimeUnit.NANOSECONDS.toMillis(timeToLive - end), this.duration );
}
}
}
Here is what one runs output looks like
NOTE: All times are in milliseconds
Finished Elapsed Time = 999, scheduled for 1000
Finished Elapsed Time = 2998, scheduled for 3000
Finished Elapsed Time = 5999, scheduled for 6000
Finished Elapsed Time = 1994, scheduled for 2000
Finished Elapsed Time = 8994, scheduled for 9000
Finished Elapsed Time = 6993, scheduled for 7000
Finished Elapsed Time = 6993, scheduled for 7000
Finished Elapsed Time = 5993, scheduled for 6000
Finished Elapsed Time = 5998, scheduled for 6000
After reading the whole last night about threads, i have discovered that the solution for my problem was not that hard.
The idea was to edit the condition of the stopping loop inside the thread so we control it by giving it a specific amount of time to run for it and here is my Example :
class ProcessorCordm extends Thread {
int runningtime;
public ProcessorCordm(int runningtime) {
this.runningtime = runningtime;
}
public void run() {
int loop = 1;
long StartTime = System.currentTimeMillis() / 1000;
for (int i = 0; i < loop; ++i) {
int rdmCross2 = (int) (Math.random() * allPopulation.size()); // Crossover 1st vector
int rdmCross1 = (int) (Math.random() * allPopulation.size());
Vector muted = new Vector();
Vector copy = copi((Vector) allPopulation.get(rdmCross2));
Vector callp = copi((Vector) allPopulation.get(rdmCross1));
muted = crossover(callp, copy);
System.out.println("cross over Between two Randoms ----------->");
affiche_resultat(muted);
addsolution(muted);
loop++;
if (timevalue < ((System.currentTimeMillis() / 1000) - StartTime)) {
loop = 0;
}
}
}
}
So if i want to run my Thread for 10 seconds i only need to :
ProcessorCoG CrossOpg = new ProcessorCoG(10);
And fo my case, I have to call many Threads simultaneously working for a specific TimeValue so i used the ExecutorServiceClass :
ProcessorCoG CrossOpg = new ProcessorCoG(timevalue);//extends Thread class
ProcessorCordm CrossOp = new ProcessorCordm(timevalue);//extends Thread class
ProcessorCordm CrossOp2 = new ProcessorCordm(timevalue);//extends Thread class
MutateGb MutGb = new MutateGb(timevalue);//extends Thread class
MutateRdm MutRdm = new MutateRdm(timevalue);//extends Thread class
MbsRdm MbsR = new MbsRdm(timevalue);//extends Thread class
ExecutorService executor = Executors.newFixedThreadPool(6);
executor.submit(MutGb);
executor.submit(MutRdm);
executor.submit(CrossOp);
executor.submit(CrossOp2);
executor.submit(CrossOpg);
executor.submit(MbsR);
I'm writing a fairly simple 2D multiplayer-over-network game. Right now, I find it nearly impossible for myself to create a stable loop. By stable I mean such kind of loop inside which certain calculations are done and which is repeated over strict periods of time (let's say, every 25 ms, that's what I'm fighting for right now). I haven't faced many severe hindrances this far except for this one.
In this game, several threads are running, both in server and client applications, assigned to various tasks. Let's take for example engine thread in my server application. In this thread, I try to create game loop using Thread.sleep, trying to take in account time taken by game calculations. Here's my loop, placed within run() method. Tick() function is payload of the loop. It simply contains ordered calls to other methods doing constant game updating.
long engFPS = 40;
long frameDur = 1000 / engFPS;
long lastFrameTime;
long nextFrame;
<...>
while(true)
{
lastFrameTime = System.currentTimeMillis();
nextFrame = lastFrameTime + frameDur;
Tick();
if(nextFrame - System.currentTimeMillis() > 0)
{
try
{
Thread.sleep(nextFrame - System.currentTimeMillis());
}
catch(Exception e)
{
System.err.println("TSEngine :: run :: " + e);
}
}
}
The major problem is that Thread.sleep just loves to betray your expectations about how much it will sleep. It can easily put thread to rest for much longer or much shorter time, especially on some machines with Windows XP (I've tested it myself, WinXP gives really nasty results compared to Win7 and other OS). I've poked around internets quite a lot, and result was disappointing. It seems to be fault of the thread scheduler of the OS we're running on, and its so-called granularity. As far as I understood, this scheduler constantly, over certain amount of time, checks demands of every thread in system, in particular, puts/awakes them from sleep. When re-checking time is low, like 1ms, things may seem smooth. Although, it is said that WinXP has granularity as high as 10 or 15 ms. I've also read that not only Java programmers, but those using other languages face this problem as well.
Knowing this, it seems almost impossible to make a stable, sturdy, reliable game engine. Nevertheless, they're everywhere.
I'm highly wondering by which means this problem can be fought or circumvented. Could someone more experienced give me a hint on this?
Don't rely on the OS or any timer mechanism to wake your thread or invoke some callback at a precise point in time or after a precise delay. It's just not going to happen.
The way to deal with this is instead of setting a sleep/callback/poll interval and then assuming that the interval is kept with a high degree of precision, keep track of the amount of time that has elapsed since the previous iteration and use that to determine what the current state should be. Pass this amount through to anything that updates state based upon the current "frame" (really you should design your engine in a way that the internal components don't know or care about anything as concrete as a frame; so that instead there is just state that moves fluidly through time, and when a new frame needs to be sent for rendering a snapshot of this state is used).
So for example, you might do:
long maxWorkingTimePerFrame = 1000 / FRAMES_PER_SECOND; //this is optional
lastStartTime = System.currentTimeMillis();
while(true)
{
long elapsedTime = System.currentTimeMillis() - lastStartTime;
lastStartTime = System.currentTimeMillis();
Tick(elapsedTime);
//enforcing a maximum framerate here is optional...you don't need to sleep the thread
long processingTimeForCurrentFrame = System.currentTimeMillis() - lastStartTime;
if(processingTimeForCurrentFrame < maxWorkingTimePerFrame)
{
try
{
Thread.sleep(maxWorkingTimePerFrame - processingTimeForCurrentFrame);
}
catch(Exception e)
{
System.err.println("TSEngine :: run :: " + e);
}
}
}
Also note that you can get greater timer granularity by using System.nanoTime() in place of System.currentTimeMillis().
You may getter better results with
LockSupport.parkNanos(long nanos)
altho it complicates the code a bit compared to sleep()
maybe this helps you.
its from david brackeen's bock developing games in java
and calculates average granularity to fake a more fluent framerate:
link
public class TimeSmoothie {
/**
How often to recalc the frame rate
*/
protected static final long FRAME_RATE_RECALC_PERIOD = 500;
/**
Don't allow the elapsed time between frames to be more than 100 ms
*/
protected static final long MAX_ELAPSED_TIME = 100;
/**
Take the average of the last few samples during the last 100ms
*/
protected static final long AVERAGE_PERIOD = 100;
protected static final int NUM_SAMPLES_BITS = 6; // 64 samples
protected static final int NUM_SAMPLES = 1 << NUM_SAMPLES_BITS;
protected static final int NUM_SAMPLES_MASK = NUM_SAMPLES - 1;
protected long[] samples;
protected int numSamples = 0;
protected int firstIndex = 0;
// for calculating frame rate
protected int numFrames = 0;
protected long startTime;
protected float frameRate;
public TimeSmoothie() {
samples = new long[NUM_SAMPLES];
}
/**
Adds the specified time sample and returns the average
of all the recorded time samples.
*/
public long getTime(long elapsedTime) {
addSample(elapsedTime);
return getAverage();
}
/**
Adds a time sample.
*/
public void addSample(long elapsedTime) {
numFrames++;
// cap the time
elapsedTime = Math.min(elapsedTime, MAX_ELAPSED_TIME);
// add the sample to the list
samples[(firstIndex + numSamples) & NUM_SAMPLES_MASK] =
elapsedTime;
if (numSamples == samples.length) {
firstIndex = (firstIndex + 1) & NUM_SAMPLES_MASK;
}
else {
numSamples++;
}
}
/**
Gets the average of the recorded time samples.
*/
public long getAverage() {
long sum = 0;
for (int i=numSamples-1; i>=0; i--) {
sum+=samples[(firstIndex + i) & NUM_SAMPLES_MASK];
// if the average period is already reached, go ahead and return
// the average.
if (sum >= AVERAGE_PERIOD) {
Math.round((double)sum / (numSamples-i));
}
}
return Math.round((double)sum / numSamples);
}
/**
Gets the frame rate (number of calls to getTime() or
addSample() in real time). The frame rate is recalculated
every 500ms.
*/
public float getFrameRate() {
long currTime = System.currentTimeMillis();
// calculate the frame rate every 500 milliseconds
if (currTime > startTime + FRAME_RATE_RECALC_PERIOD) {
frameRate = (float)numFrames * 1000 /
(currTime - startTime);
startTime = currTime;
numFrames = 0;
}
return frameRate;
}
}