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.