I know using Timer and TimerTask is no longer the current accepted practice (some have suggested using threads, others suggest using ScheduledExecutorService or its variants), so this question is not so much about good programming practice, but about the possibility of actual errors or exception.
Essentially, what I have is a servlet that keeps a running counter (which is a static Calendar object) that gets incremented every second. When a specified deadline is met (when we reach 10 minutes by default), I make a call from my application to a NIST time server to get the current time, which I then use to re-set my counter.
The same TimerTask-defined method that increments the counter (every second) is also the one that must be paused and re-scheduled every time I make a call to a NIST server (every ten minutes). I have been unsuccessful in pausing/cancelling the existing Timer/TimerTask objects before the NIST server call and re-scheduling the TimerTask after the call.
The exceptions that occur from this are described here:
How do I use a timer in Java when required to set and cancel multiple times?
Suffice it to say, neither TimerTask nor Timer can be scheduled more than once, even by using purge() or cancel(), which appear to be only good for setting those objects as eligible for Java garbage collection.
Using wait() and notify() resulted in synchronization exceptions that I, unfortunately, did not have the time to figure out, so my initial experiment with threading was a failure.
What I ended up doing is this:
secondTickerTask.cancel();
secondTicker.purge();
secondTicker.cancel();
secondTickerTask = null;
secondTicker = null;
Date newCurrentTime = getNistTimeFromFirstWorkingServer();
// Save new date to current time, reset second counter.
setCurrentTimeAndDeadline(newCurrentTime);
startSecondIncrementTimer(newCurrentTime);
secondTicker = new Timer();
secondTickerTask = new TimerTask(){
public void run(){
incrementCurrentTimeAndTestDeadline();
}
I ran this code over-night a few times, at 10-minute and 1-minute intervals between NIST server calls, and it worked smoothly.
So, after that long lead-up (thank you for your patience), this is what my question is: Being forced, for the moment, to use the code that I have, is there any damage that could result in the long run? If I keep making new TimerTask and Timer objects while nulling out the old ones over, let's say, a period of a month, or six months, will I force the Server to run out of memory? Is Java's garbage collection robust enough to handle this sort of use? Can any other scary thing happen?
Thank you very much for your time,
- Eli
Java will handle the creation and abandonment of the timer tasks just fine. You need to ensure that you drop all references to the timers when you are done with them, which it appears you are doing, and then when the GC runs it will clean up any garbage the Timers introduced.
You are safe.
You should note that, over long periods of time, some Java processes tend to keep allocating memory until they hit their -Xmx limit. This does not mean that there is a problem (because that space will be reused by the GC), but it also means that, if you want a long-running Java process to have a relatively small footprint that you should not specify an -Xmx much larger than what you actually need.
Related
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.
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.
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.
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 :)
What is both faster and "better practice", using a polling system or a event based timer?
I'm currently having a discussion with a more senior coworker regarding how to implement some mission critical logic. Here is the situation:
A message giving an execution time is received.
When that execution time is reached, some logic must be executed.
Now multiple messages can be received giving different execution times, and the logic must be executed each time.
I think that the best way to implement the logic would be to create a timer that would trigger the logic when the message at the time in the message, but my coworker believes that I would be better off polling a list of the messages to see if the execution time has been reached.
His argument is that the polling system is safer as it is less complicated and thus less likely to be screwed up by the programmer. My argument is that by implementing it my way, we reduce the reduce the computational load and thus are more likely execute the logic when we actually want it to execute. How should I implement it and why?
Requested Information
The only time my logic would ever be utilized would almost certainly be at a time of the highest load.
The requirements do not specify how reliable the connection will be but everyone I've talked to has stated that they have never heard of a message being dropped
The scheduling is based on an absolute system. So, the message will have a execution time specifying when an algorithm should be executed. Since there is time synchronization, I have been instructed to assume that the time will be uniform among all machines.
The algorithm that gets executed uses some inputs which initially are volatile but soon stabilize. By postponing the processing, I hope to use the most stable information available.
The java.util.Timer effectively does what your colleague suggests (truth be told, in the end, there really aren't that many ways to do this).
It maintains a collection of TimerTasks, and it waits for new activity on it, or until the time has come to execute the next task. It doesn't poll the collection, it "knows" that the next task will fire in N seconds, and waits until that happens or anything else (such as a TimerTask added or deleted). This is better overall than polling, since it spends most of its time sleeping.
So, in the end, you're both right -- you should use a Timer for this, because it basically does what your coworker wants to do.