Well, this is tricky. I'll try to explain it thoroughly.
First of all, the precision of a system timer is not one millisecond, it may be substantially higher. Let's assume that the precision of your system timer is the same as mine - 15 milliseconds. That means that the value of
System.currentTimeMillis() changes only once every 15 ms, about 66 times per seconds.
The for-loop (line 21) runs for ten thousand iterations or for one second, whichever comes first.
Java is pretty fast nowadays and when there is no sleep() in the for-loop (line 22 commented out), the for-loop actually completes not only faster than one second, but well under 15 ms, so fast that the value of the system timer does not change.
Because the value of the system timer didn't change while the loop was executed, the value of the
exeTime variable is 0 (zero). The
sleepTime has then a value of 1000. The sleep() at line 32 does not execute when the sleepTime is 1000 (see the condition above), so the method continues with printStat() and then task() is called again, causing the process to repeat (more on this later).
As the for-loop runs well below 15 ms, this whole cycle can be repeated several times during one 15 ms interval, causing multiple printouts with the same second. Just when the for-loop starts close to the end of the 15 ms interval, the system timer changes before the loop completes. At this moment the
exeTime will be equal to the value of system timer precision (15 ms). The
sleepTime is then computed as 1000 - 15 = 985, and the sleep() at line 32, which is now allowed by the condition on line 31, pauses the execution for the rest of the second. The printStat() called in this iteration will probably write a new second on the screen.
What changes when Thread.sleep(0) is called? The Thread.sleep() is more time consuming operation than, for example, an addition or a simple method call. Executing it 10000 times takes more time than 15 ms, the resolution of the timer (it's actually between 30 and 45 ms on my system). This means that the value of the system timer is guaranteed to change while the for-loop is executing and therefore the
exeTime will be nonzero. Consequently
sleepTime is less than 1000, allowing the Thread.sleep() at line 32 to pause the execution for the rest of the second. Therefore printStat() is called roughly once per second in this case.
(My computer is probably faster than yours - I get dozens of printouts with the same second. It is also possible that the for-loop with Thread.sleep(0) takes more than one second on your system, in which case it is aborted by the break, and sleepTime is then <= 0. The end result is the same - about one call to printStat() every second.)
Modify your program so that it prints the values of exeTime and sleepTime before the printStat() call and you'll quite clearly see all this happening.
This whole enterprise is unnecessary to achieve your goal. If you need to pause the execution for a second, just call Thread.sleep(1000). If you're not doing time-critical operations (eg. playing a video file), you may probably well ignore the additional time it will take to do the processing. No one will ever notice.
However, there is another serious bug in your code. You made an infinite loop by calling the task() method recursively. This will inevitably lead to an StackOverflowError exception. Try it - comment out lines 15 to 34 in your code, the exceptions appears immediately.
Your task() method should therefore look like this:
That's probably all you need.