Reputation: 25
In Java, I have a loop which calls a method, and then that method has a sin which takes as parameter the time since the execution of the program. This loop runs at constant 60 updates per second (with the expected variations of +-1 or 2 ups). What I want to do is call a method within that loop, but that method must be called every 0.2, 0.4... seconds (fixed interval) , so what I did was:
if(executionTime % 200 == 0)
But that wasn't enough because it isn't always exact so it skipped a lot of times. For that matter I tried if(executionTime % 200 <= 50)
to try and limit it, but it still skipped a few times, but less than before. So my question is if there is any way to have it run exactly at 0.2 seconds, with the following details:
What I'm using this is to call sin with a variable that is incremented by some number every time the method is called (this is where the method must be called every 200 ms). Essentialy I want to do something similar to graphing a function that depends on time(X), where X is incremented by the same number every 200 ms of loop iteration. So, each loop iteration, a new point of the graph is calculated every 200 ms. What I could do is check before each call to other methods within the loop if it is time to call this method, but that ruins the order of the loop. I've searched around, but I can only find scheduling, which I believe doesn't do it.
EDIT: Pseudocode:
int increment;
while(running){
first();
second();
if(condition)
doSomething();
if(timeCheck) // time check every 200ms; this is what I don't know how to do
graphfunction(increment);
}
Upvotes: 1
Views: 1230
Reputation: 274
You can use Thread.sleep()
long time1 ,time2;
while (true) {
time1 = System.currentTimeMillis();
yourMethod();
time2 = System.currentTimeMillis();
if((time2-time1) <200)
Thread.sleep(200-(time2-time1));
}
Upvotes: 0
Reputation: 109547
You are doing something graphical, probably for the Swing GUI. Use a swing Timer, instead of looping. This is optimal. If the calculation takes too long, drop a frame: check on a timer callback doing the calculation, whether no prior calculation is still being done.
In fact, if you on the timer callback display the calculated result of the prior calculation, repaint
/ repaintImmediately
, and then start the next calculation, the frame rate is held as exact as possible.
Maybe using double buffering:
BufferedImage actualShown = new BufferedImage(...);
// Could be local to graphfunction:
BufferedImage beingCalculated = new BufferedImage(...);
@Override
public void repaintComponent(Graphics g) { // Called via repaint
g.drawImage(actualShown, 0, 0);
}
void graphfunction(int increment) {
// First draw old frame:
repaint();
// Calculations:
... beingCalculation.setRGB(x, y, Color.BLACK);
// Double buffering:
BufferedImage next = actualShown;
actualShown = beingCalculated;
beingCalculated = next;
}
Upvotes: 0
Reputation: 4228
I would use the java.util.concurrent
's ExecutorService
. Take a look at the Javadoc. Use the following method on that object
ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
Javadoc:
Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with the given period; that is executions will commence after initialDelay then initialDelay+period, then initialDelay + 2 * period, and so on.
Upvotes: 2