Most optimal way to detect multiple timers / countdowns hitting 0? - java

I am writing to see what everyone's way of doing this is.
Example:
I have multiple timers with a start time of potentially anything. E.G, One timer could be 30 seconds, the second could be 10 minutes, the third could be 3mins 32seconds, and so on... You can create infinite timer countdowns.
Now, the question is... What's the best way to detect when a timer hits 0? Java does have a runnable class and I was going to run an async task to check every second but this sounds really inefficient to me.
Are there any other ways to do it? Thanks!

Related

what if a Timer falls behind schedule

I am using a java.util.Timer class. I use it to execute repetitive tasks. (e.g. a polling mechanism that checks a status every second).
timer.scheduleAtFixedRate(new Poller(), 0, pollingInterval);
The problem case is: timers can fall behind. e.g. If they need to execute every second, and the task takes 2 seconds to execute.
The documentation says that the timer will try to catch-up. e.g. Suddenly if the tasks only takes half a second to execute, it will speed up.
First of all, I am wondering, is there a built-in way to detect if it's running behind.
But anyway, I am looking for a way to disable the catching-up behavior.
If it falls behind, I just want it to skip a couple of cycles.
(I've also used a ScheduledThreadPoolExecutor for similar tasks. It has more options, and maybe that can be the solution. But it's a bit too overwhelming to find it.)
EDIT:
Now that I think about it, I think the way to do it with a ScheduledThreadPoolExecutor, is to use the scheduleWithFixedDelay method, which uses an interval between task execution.
Still, is there a way to achieve the same with a Timer?
If you don't care if the timer falls behind, why not use a simple while loop with a Thread.sleep, such as:
while(condition) {
// do work here
Thread.sleep(1000L);
}
If this falls behind due to OS scheduling constraints, it will never try to make up the time that was lost. It will always delay for at least the amount of time you specify. Remember, simple is better than complex.

Java ScheduledExecutorService behind the scenes

How does things like scheduleAtFixedRate work? How does it work behind the scenes and is there a penalty to using it?
More specifically, I have a task that I want to run periodically, say every 12 hours. The period is not strict at all, so my first instinct was to check in every request (tomcat server) if it's been more than >12 hours since the task last executed and if so, execute it and reset the timer. The downside of this is that I have to do a small time check on every request, make sure the task is run only once (using a semaphore or something similar) and the task might not execute in a long time if there's no requests.
scheduleAtFixedRate makes it easier to schedule a recurring task, but since I don't know how it does it, I don't know what the performance impact is. Is there a thread continually checking if the task is due to run? etc.
edit:
In Timer.java, there's a mainLoop function which, in my understanding, is something like this (overly simplified):
while(true) {
currentTime = System.currentTimeMillis();
if(myTask.nextExecutionTime == currentTime) myTask.run();
}
Won't this loop try to run as fast as possible and use a ton of CPU (I know, obviously not, but why)? There's no Thread.sleep in there to slow things down.
You can read the code if you wish to work out how it works.
There is an overhead using ScheduledExecutorService in terms of CPU and memory, however on the scale of hours, minutes, second even milli-seconds, it probably not work worrying about. If you have a task running in the range of micro-seconds, I would consider something more light weight.
In short, the overhead is probably too small for you to notice. The benefit it gives you is ease of use, and it is likely to be worth it.

Can I use the Java timer class for timed data collection?

I am writing a program that collects a series of angle inputs during a trial and saves these to a file with their corresponding timestamps.
For example:
1 sec 260 degrees
2 sec 45 degrees
3 sec 60 degrees
etc.
When running a trial, the user should be able to pause and restart or fully abort the trial if need be.
I am running into trouble with the pause functionality. I have been using the Java Timer and TimerTask classes to time the input, as it provides much of the functionality I am looking for (start a task after a delay, only record data at certain intervals, etc.).
Within my timerTask, I have been storing the collected angles and times in parallel arrays, and then at the end of the trial, writing these arrays to a file.
However, when I "pause" my timerTask via the timer.cancel() function and restart it, the old data arrays are thrown away. I have tried to sidestep this issue by saving the "paused" array and then merging it with the "restarted" array at the end of the restarted trial, but this doesn't account for the fact that a trial could be paused numerous times.
Are the timer/timerTask classes the wrong classes to be using for this job? Is there a better way to collect time-based data in Java? Or am I just overlooking a solution?
As the API specifies Timer.cancel()
Terminates this timer, discarding any currently scheduled tasks.
The simplest way to achieve the functionality you desire would probably be to store a 'paused' boolean and toggle it when the user pauses/unpauses. Then check the state of the boolean from within your task and simply return; if the trial is paused. The Timer will still fire every second, but nothing will happen as long as the trial is paused.

Java timer task runs slower than normal

Part of an application I'm writing uses a chronometer system. The timer should tick once every ms.
In my chronometer, I have these variables.
private static final int DELAY_IN_MILLISECONDS = 0;
private int intervalInMilliseconds = 1;
I start the timer like this:
timer = new Timer();
timer.schedule(new Task(), DELAY_IN_MILLISECONDS,
getIntervalInMilliseconds());
Yet, after a second he only reached about +- 100ms instead of 1000ms.
Though he used to work fine, untill I've added code to a different part of the game. I'm rather sure I've changed nothing on the timer but yet he became slower than normal (he used to work fine at first).
Is it possible that my timer runs slower due to the application requiring too much CPU time for other things? (it's a game I'm creating). If so, what would be the conventional way to solve this? Keeping in mind that it's more important the game runs smooth than the timer.
Thanks in advance!
EDIT: Is there a way to find out which part of your application is "bottlenecking" it, such as check where he uses most resources etc?
If long-term accuracy of scheduling is what you are after, then you should use the Timer#scheduleAtFixedRate method. If you continually reschedule the task with a delay, then the Timer instance cannot compensate for its past timing errors.
If short-term accuracy is also a concern, then you should switch to the Scheduled Executor Service, which uses a more accurate low-level technique to schedule the tasks.
I actually have a bit of a ad-hoc solution to the problem.
I stopped counting every ms, and just did the +=15ms to counter for the sleep();
The timer runs smooth now and after a minute I had less than 1second difference with the actual time it should have been.
Thanks everyone for your help, but any other (less ad-hoc) solutions are still very welcome!
EDIT: I just got this method due to Boris, so you can post your comment as an answer if you like :)

Timer implementation

How can you implement some kind of timer, to know how much time did user spend for one round of a game?
Getting System.currentTimeMillis will get your system time to the millisecond. If you want to do a Swing event intermittently, such as displaying the current time in a stop watch or a simple animation, then a Swing Timer would work well.
One can easily find the time spent by a user on one round of a game by using System.nanoTime() function. However if you want to implement in a game, you would probably like the timer to also be displayed to the user, you can you use multi-threading for the same.

Categories

Resources