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 :)
Related
In my server and client main loops, I have custom timers. They're pretty basic things. I'm using System.currentTimeMillis() to get the milliseconds and then comparing it to different variables for different timers. If the timer variable is less than tickCount, it runs the code, then sets the timer to tickCount + UpdateTime.
Here is an example:
long tickCount = System.currentTimeMillis();
if (LastUpdateTime_WoodCutting < tickCount) {
woodcutting();
LastUpdateTime_WoodCutting = tickCount + UpdateTime_WoodCutting;
}
UpdateTime_WoodCutting is set to 10. In theory, this should update this timer every 10ms. I'm sure it's not exactly that accurate, but the problem I'm having is, overall, this timer is meant to be a 10 second timer, which would be 10000ms.
The timer seems to be taking anywhere from 20-30 seconds to get there. The woodcutting method just checks if the timer in the player class is less than 10000, and if so, it adds 10 to it and once it's at 10000 or more, it executes the code for cutting down a tree in the game.
Another problem is that the client uses the exact same code for timers as the server, yet even while running on the same machine, they do not line up. The client's timer seems to finish about halfway through the server's timer. I've tried a bunch of alternatives to System.currentTimeMillis() but they all pretty much work exactly the same, so it hasn't been very fruitful.
Basically, what I'm trying to figure out is how I should handle these timers. It doesn't appear that I'm handling them properly. Before a bunch of changes to my code, these timers worked flawlessly, but all of a sudden, they do not. I don't know if it is the result of updating Gradle or Java (from 1.7 to 1.8), but I'm very frustrated with this and it's a pretty game breaking issue.
My source code is easily almost 40k lines of code and I am unable to share all of my code, but anything someone may need to see in order to better help me with this, I will provide what I can.
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 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.
I can't seem to figure out how to make a simple timer in java. All I need it to do is just display time, really. So just a start method, and it keeps counting up like 0:00, 0:01, 0:02, etc. I've seen some other similar forum posts on this, but all the code is kind of complicated for my level of understanding; I'm kind of new to java. But it shouldnt be that hard to make a timer that just performs such a basic function? If anyone could help it would be greatly appreciated :)
This is not difficult. However, I would caution you that I have seen some very confused answers on stack overflow, in some cases shockingly poor coding habits, so be very careful. First let me answer the question.
If seem that the biggest mistake that programmers make in implementing a timer, is thinking that they need something to keep track of the current time. That is, they write some sort of loop that increments a variable every second or some such silly thing. You do not need to write code to keep track of the time. The function System.currentTimeMillis() will do that for you, and it does it quite accurately.
Timer code will involve two aspects which many programmers mix up:
calculation of the time
refresh of the display
All you need to do to calculate the time to display, is to record the time that the timer started:
long startTime = System.currentTimeMillis();
Later, when you want to display the amount of time, you just subtract this from the current time.
long elapsedTime = System.currentTimeMillis() - startTime;
long elapsedSeconds = elapsedTime / 1000;
long secondsDisplay = elapsedSeconds % 60;
long elapsedMinutes = elapsedSeconds / 60;
//put here code to format and display the values
The biggest mistake that programmers make is to think they need a variable to hold the current time and then to write code to increment that variable every second, e.g. something called "elapsedSeconds" which they maintain. The problem is that you can schedule code to be called every second, but there is no guarantee of exactly when that code will be called. If the system is busy, that code might be called quite a bit later than the second. If the system is extremely busy (for example page fetching from a faulty disk) it could actually be several seconds late. Code that uses the Thread.sleep(1000) function to loop every second will find that the error builds up over time. If sleep returns 300ms late one time, that error is compounded into your calculation of what time it is. This is all completely unnecessary because the OS has a function to tell you the current time.
The above calculation will be accurate whether you run this code every second, 100 times a second, or once every 3.572 seconds. The point is that currentTimeMillis() is the accurate representation of the time regardless of when this code is called -- and that is an important consideration because thread and timer events are not guaranteed to be accurate at a specific time.
The second aspect of a timer is refresh of the display. This will depend upon the technology you are using to display with. In a GUI environment you need to schedule paint events. You would like these paint events to come right after the time that the display is expected to change. However, it is tricky. You can request a paint event, but there may be hundreds of other paint events queued up to be handled before yours.
One lazy way to do this is to schedule 10 paint events per second. Because the calculation of the time does not depend on the code being called at a particular point in time, and because it does not matter if you re-paint the screen with the same time, this approach more or less guarantees that the displayed time will show the right time within about 1/10 of a second. This seems a bit of a waste, because 9 times out of 10 you are painting what is already on the screen.
If you are writing a program with animation of some sort (like a game) which is refreshing the screen 30 times a second, then you need do nothing. Just incorporate the timer display call into your regular screen refresh.
If paint events are expensive, or if you are writing a program that does terminal-style output, you can optimize the scheduling of events by calculating the amount of time remaining until the display will change:
long elapsedTime = System.currentTimeMillis() - startTime;
long timeTillNextDisplayChange = 1000 - (elapsedTime % 1000);
The variable timeTillNextDisplayChange holds the number of milliseconds you need to wait until the seconds part of the timer will change. You can then schedule a paint event to occur at that time, possibly calling Thread.sleep(timeTillNextDisplayChange) and after the sleep do the output. If your code is running in a browser, you can use this technique to update the page DOM at the right time.
Note, that there is nothing in this calculation of the display refresh that effects the accuracy of the timer itself. The thread might return from sleep 10ms late, or even 500ms late, and the accuracy of the timer will not be effected. On every pass we calculate the time to wait from the currentTimeMillis, so being called late on one occasion will not cause later displays to be late.
That is the key to an accurate timer. Do not expect the OS to call your routine or send the paint event exactly when you ask it to. Usually, of course, with modern machines, the OS is remarkably responsive and accurate. This happens in test situations where you are not running much else, and the timer seems to work. But, in production, under rare stress situation, you do not want your timer "drifting" because the system is busy.
You can either use Timer class from java.util or another way, which is more complicated, is with Threads. Timer also has thread action, but it's pretty easy to understand to use it.
For creating a simple timer as you explained as per your need , it is very easy to write a code for that. I have written the below code for your reference. If you wish you can enhance it.
import java.util.concurrent.TimeUnit;
public class PerfectTimer {
public static void main(String[] args) throws InterruptedException
{
boolean x=true;
long displayMinutes=0;
long starttime=System.currentTimeMillis();
System.out.println("Timer:");
while(x)
{
TimeUnit.SECONDS.sleep(1);
long timepassed=System.currentTimeMillis()-starttime;
long secondspassed=timepassed/1000;
if(secondspassed==60)
{
secondspassed=0;
starttime=System.currentTimeMillis();
}
if((secondspassed%60)==0)
displayMinutes++;
System.out.println(displayMinutes+"::"+secondspassed);
}
}
}
if you want to update something in the main thread (like UI components)
better to use Handler
Handler h = new Handler();
h.postDelayed(new Runnable() {
#Override
public void run() {
//do something
}
}, 20);
20 - the delay In MS to do something.
and run it in a loop.
I have created a Timer that has everything you might need in it.
I even documented it!
And I also compiled it for faster usage.
Here's an example:
//...
//For demo only!
public static void main(String[]a){
Timer timer=new Timer();
timer.setWatcher(new Timer.TimerWatcher(){
public void hasStopped(boolean stopped){
System.out.print(stopped+" | ");
}
public void timeElapsed(long nano, long millis, long seconds){
System.out.print(nano+", ");
System.out.print(millis+", ");
System.out.print(seconds+" | ");
}
public void timeLeft(long timeLeft){
System.out.print(timeLeft+"\r");
}
});
//Block the thread for 5 seconds!
timer.stopAfter(5, Timer.seconds); //You can replace this with Integer.MAX_VALUE.
//So that our watcher won't go to waste.
System.out.println();
}
//...
This is not for promotion, made this to help people not waste their time in coding classes themselves!