Executing a method X number of times per second in Java - java

I have a task to execute a given method X times per second (example 30 times per second). Within that tick method, I should show the current speed (basically display FPS).
I don't even know how to start. Tried googling but didn't really help.

To show something like "fps":
public static void main(String[] args) {
while (true) callMethod();
}
private static long lastTime = System.currentTimeMillis();
public static void callMethod() {
long now = System.currentTimeMillis();
long last = lastTime;
lastTime = now;
double fps = 1000 / (double)(now - last);
System.out.println(fps);
}
You might have to add some sleeps, because otherwise the difference between two steps is just too small, the fps will be "Infinity".
The requirement for 30 times a second is something entirely different. As I said in my comment already that is basically the exact opposite of fps since 30 times a second means exactly 30 fps, which means there is no need to calculate the fps because that is the original requirement.
Further note that "30 times a second" in itself is a generally bad requirement for at least two reasons:
is 1000 times a second okay? Does that fulfil the requirement
is running the method 30 times in the first millisecond and then waiting the remaining 999ms a useful solution to the problem?

Related

how to run a code 60 times per second in java

if I don't control the number of times per second my code executes, when I add a line, the program varies and I have to adjust the constants again. (translated by Google)
My code running out of control:
public builder(){
while(true)
stepEvent();
}
private void stepEvent() {
setOfActions();
repaint();
}
This is just one way to do it(it's very long but VERY precise - I recommend it for game development). In this case I'm using the run() method from the Runnable interface to execute the code.
public void run(){
long lastTime = System.nanoTime();
final double ns = 1000000000.0 / 60.0;
double delta = 0;
while(true){
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while(delta >= 1){
the code you want to be executed
delta--;
}
}
}
Explanation Line by Line:
Basically, I store the current time in nanoseconds in lastTime. Then in ns I store 1/60th of a second in nanoseconds and create a variable delta.
After this, I go inside the infinite while loop(it doesn't have to be infinite) and store the current time in nanoseconds once again in now. This is to take into account the amount of time that took the computer to go from the lastTime declaration line to the while loop line.
After doing all this, I add to delta the difference of now and lastTime divided by the 1/60th of a second(ns) I mentioned. This means that every time delta is equal to 1, 1/60th of a second will have passed.
Right after this, I make lastTime be the same as now. In the while loop that comes afterwards I check if delta is equal or greater than 1 and then in there you should put all the code you want to be executed 60 times per second. Don't forget to substract 1 from delta so it doesn't loop endlessly.
Analyze the code thoroughly and see if you can understand it. If you can't, I'll clarify further. I insist that this is just one possible way to do it, but there are many more ways.
Note: In some cases, you will never even need delta, but it is very helpful for some purposes.
Credit for the code: Most of this code(at least where I got it & learned it) is extracted from TheCherno's Game Programming Series
Have a great day!
import java.util.Timer;
import java.util.TimerTask;
public class HelloWorld {
public static void main(String []args) {
// number of ms in 1/60 of a second
// there will be some rounding error here,
// not sure if that's acceptable for your use case
int ms = 1000 / 60;
Timer timer = new Timer();
timer.schedule(new SayHello(), 0, ms);
}
}
class SayHello extends TimerTask {
public void run() {
System.out.println("Hello World!");
}
}
Basically, you have to execute your stepEvent every 17 ms.
With the assumption you want to run sequentially, you could stop the execution during a defined period by using Thread.sleep(millis , nanos). In this case, we will stop the thread 17ms minus the stepEvent execution time (think to add condition to avoid negative value in sleep function)
long startedTime;
for(;;){
startedTime = System.currentTimeMillis();
stepEvent();
Thread.sleep(17 - System.currentTimeMillis() + startedTime);
}
Otherwise you can use the ScheduledExecutorService which allows you to schedule code to run periodically at fixed time intervals (or after a specified delay). In this case, you can execute your step at a fixed rate every 17ms.
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
scheduledExecutorService.scheduleAtFixedRate(YourClass::stepEvent, 0, 17, TimeUnit.MILLISECONDS);
You can also configure to use severals thread with Executors.newScheduledThreadPool

How can I set while repeat count per second?

I use a while loop to repeat my codes in my program. I want to repeat a code 1000 times per second. How can I do this?
For the fixed-delay execution of some code, it might be a better approach to use a timer object, such as java.util.Timer or javax.swing.Timer, or even AnimationTimer, depending on what you're trying to accomplish. This being said, it's not possible to guarantee a frequency and a frequency of 1000/s (or period of 1ms) is quite fast, and java.util.Timer and javax.swing.Timer won't be able to keep up.
See also:
How to use swing timers
How to use Java.Util.Timer
High Resolution Timer in Java 5
I will show you an example of this using System.nanoTime() to determine how much time has passed, and will explain why your premise typically does not make much sense and you probably should not do this.
First off here is code that will execute a block of code 1000 times and will take 1 second to finish every time, as long as that code can be executed that quickly.
long startTime = System.nanoTime();
long currentTime = startTime;
int counter = 0;
while (((currentTime - startTime) < 1_000_000_000) || counter < 1000) { //Executes until 1 second has passed AND it has iterated 1000 times
counter++;
currentTime = System.nanoTime();
if (counter < 1000) {
//The code you want to execute 1000 times
System.out.println(counter);
}
}
System.out.println((currentTime - startTime)/1_000_000 + " milliseconds have passed.");
Now the problem with this code is you will obviously hit the 1000 executions before you hit 1 second, so it will sit in the loop doing nothing after the 1000 executions are completed to ensure the total time of the loop takes 1 second.
However what happens if that block of code takes so long that you cannot complete that code 1000 times within a second? It is impossible to go the other direction and add extra time to complete the 1000 executions, the 1000 executions will no longer take 1 second and it is impossible to fix this. The only way this can be done, is if you know that 1000 executions will be completed under 1 second and wait for the remaining time.
However, this does not seem like a good way to do things in general and you should not program in a way that depends on time AND loop iteration count, it just does not really make sense and there are likely better ways to do what your actual goal is.
Note: This code will only execute the block of code 1000 times, a single time. Surround all of this code by another loop if you want to do this multiple times.
EDIT:
Just to make it more clear I made an example that will take longer to execute than 1 second.
public static void main(String[] args){
long startTime = System.nanoTime();
long currentTime = startTime;
int counter = 0;
while (((currentTime - startTime) < 1_000_000_000) || counter < 1000) {
counter++;
currentTime = System.nanoTime();
if (counter < 1000) {
//The code you want to execute 1000 times
int count2 = 0;
while (count2 < 1000) { //1000 blank lines per loop to take a long time
count2++;
System.out.println();
}
System.out.println(counter);
}
}
System.out.println((currentTime - startTime)/1_000_000 + " milliseconds have passed.");
}
This will print blank lines just to ensure it takes a long time. For my system this outputted:
2831 milliseconds have passed.
The code took 2.8 seconds because time was no longer the restrictive condition, but 1000 iterations was, and there is no way to make this exact code run 1000 times per second, it is impossible.
TLDR: You can force something to take a minimum amount of a time, but you cannot force it to take a maximum amount of time.
Try to use a thread and use Thread.sleep() or System.currentTimeMillis() / 1000, this will give you the time in seconds.

How to delay a method's repeated execution?

I'm new to java and I'm trying to constantly add "zombie" entity to my game after a delay, and then shortening the delay as time goes on.
In my PlayState class I've got the code to spawn the entities in a position when my update(); method is run (which houses getInput(); and such. Not shown for clarity.)
public void update(long elapsed) {
this.entities.add(new Zombie(-535));
}
How would i make a delay that shortens? I'm guessing I would make the delay and then use a multiplier which i have getting smaller every 10 seconds or so, but how would I do this?
Now, I don't know much about the finer workings of your class, but this might give you a general idea of what I mean:
int counter = 50;
for(int i = 100; i >= 0; i--)
{
if(i == counter)
{
counter = counter / 2;
this.entities.add(new Zombie(-535));
}
}
Suppose i is the the total run-time of the game, and counter represents a percent of the game when you want to add a zombie.
If you want to add a zombie after 50% of the run-time (here, 100 seconds), then as the time reduces, you check if the time has come to add a zombie (Here, 50 seconds).
What I've done here is reduce the delay to half, and continue checking if the time has come to add a zombie.
Maybe you could call sleep on your thread of execution:
int sleepInMs = 5000
Thread.sleep(sleepInMs);
sleepInMs+=1000; //Then of course handle the case when sleepInMs == 0
Really need more information about your implementation.
For a simple delay, use "delay ms;"
Edit ms for the number of milliseconds you want. 1000 milliseconds is one second

How to generate more than 1000 events / second in java using sleep time

I have a generator which generates events for Flink CEP, code for which is given below. Basically, I am using Thread.sleep() and I have read somewhere that java can't sleep less than 1 millisecond even we use System.nanoTime(). Code for the generator is
public class RR_interval_Gen extends RichParallelSourceFunction<RRIntervalStreamEvent> {
Integer InputRate ; // events/second
Integer Sleeptime ;
Integer NumberOfEvents;
public RR_interval_Gen(Integer inputRate, Integer numberOfEvents ) {
this.InputRate = inputRate;
Sleeptime = 1000 / InputRate;
NumberOfEvents = numberOfEvents;
}
#Override
public void run(SourceContext<RRIntervalStreamEvent> sourceContext) throws Exception {
long currentTime;
Random random = new Random();
int RRInterval;
int Sensor_id;
for(int i = 1 ; i <= NumberOfEvents ; i++) {
Sensor_id = 2;
currentTime = System.currentTimeMillis();
// int randomNum = rand.nextInt((max - min) + 1) + min;
RRInterval = 10 + random.nextInt((20-10)+ 1);
RRIntervalStreamEvent stream = new RRIntervalStreamEvent(Sensor_id,currentTime,RRInterval);
synchronized (sourceContext.getCheckpointLock())
{
sourceContext.collect(stream);
}
Thread.sleep(Sleeptime);
}
}
#Override
public void cancel() {
}
}
I will specify my requirement here in simple words.
I want generator class to generate events, let's say an ECG stream at 1200 Hz. This generator will accept parameters like input rate and total time for which we have to generate the stream.
So far so good, the issue is that I need to send more than 1000 events / second. How can I do this by using generator function which is generating values U[10,20]?
Also please let me know if I am using wrong way to generate x number of events / second in the above below.
Sleeptime = 1000 / InputRate;
Thanks in advance
The least sleep time in Windows systems is ~ 10 ms and in Linux and Macintosh is 1 millisecond as mentioned here.
The granularity of sleep is generally bound by the thread scheduler's
interrupt period. In Linux, this interrupt period is generally 1ms in
recent kernels. In Windows, the scheduler's interrupt period is
normally around 10 or 15 milliseconds
Through my research, I learned that using the nano time sleep in java will not help as the issue in at OS level. If you want to send data at arrival rate > 1000 in a controlled way, then it can be done using Real-Time Operating Systems (RTOS), as they can sleep for less then a millisecond. Now, I have come up with another way of doing it, but in this solution, the interarrival times will not be constantly distributed.
Let's say you want arrival rate of 3000 events/ second, then you can create a for loop which iterates 3 times to send data in each iteration and then sleep for 1ms. So for the 3 tuples, the interarrival time will be close to one another, but the issue will be solved. This may be a stupid solution but it works.
Please let me know if there is some better solution to this.

Java calculations that takes X amount of time

This is just a hypothetical question, but could be a way to get around an issue I have been having.
Imagine you want to be able to time a calculation function based not on the answer, but on the time it takes to calculating. So instead of finding out what a + b is, you wish to continue perform some calculation while time < x seconds.
Look at this pseudo code:
public static void performCalculationsForTime(int seconds)
{
// Get start time
int millisStart = System.currentTimeMillis();
// Perform calculation to find the 1000th digit of PI
// Check if the given amount of seconds have passed since millisStart
// If number of seconds have not passed, redo the 1000th PI digit calculation
// At this point the time has passed, return the function.
}
Now I know that I am horrible, despicable person for using precious CPU cycles to simple get time to pass, but what I am wondering is:
A) Is this possible and would JVM start complaining about non-responsiveness?
B) If it is possible, what calculations would be best to try to perform?
Update - Answer:
Based on the answers and comments, the answer seems to be that "Yes, this is possible. But only if it is not done in Android main UI thread, because the user's GUI will be become unresponsive and will throw an ANR after 5 seconds."
A) Is this possible and would JVM start complaining about non-responsiveness?
It is possible, and if you run it in the background, neither JVM nor Dalvik will complain.
B) If it is possible, what calculations would be best to try to perform?
If the objective is to just run any calculation for x seconds, just keep adding 1 to a sum until the required time has reached. Off the top of my head, something like:
public static void performCalculationsForTime(int seconds)
{
// Get start time
int secondsStart = System.currentTimeMillis()/1000;
int requiredEndTime = millisStart + seconds;
float sum = 0;
while(secondsStart != requiredEndTime) {
sum = sum + 0.1;
secondsStart = System.currentTimeMillis()/1000;
}
}
You can and JVM won't complain if your code is not part of some complex system that actually tracks thread execution time.
long startTime = System.currentTimeMillis();
while(System.currentTimeMillis() - startTime < 100000) {
// do something
}
Or even a for loop that checks time only every 1000 cycles.
for (int i = 0; ;i++) {
if (i % 1000 == 0 && System.currentTimeMillis() - startTime < 100000)
break;
// do something
}
As for your second question, the answer is probably calculating some value that can always be improved upon, like your PI digits example.

Categories