• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • Liutauras Vilda
  • Jeanne Boyarsky
  • paul wheaton
Sheriffs:
  • Ron McLeod
  • Devaka Cooray
  • Henry Wong
Saloon Keepers:
  • Tim Holloway
  • Stephan van Hulst
  • Carey Brown
  • Tim Moores
  • Mikalai Zaikin
Bartenders:
  • Frits Walraven

Why my program works fine when i write Thread.sleep(0)

 
Ranch Hand
Posts: 763
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

I have below program which performs some task after every one minutes. Below is my program



output



As you can see the seconds are getting repeated.. which shouldn't get repeated... but if i uncomment the Thread.sleep(0) line the program works just perfectly fine. it executes the task accurately after every 1 second.

What could be the possible reason ? Will my program ever work fine without Thread.sleep(0); ???

 
Sheriff
Posts: 3837
66
Netbeans IDE Oracle Firefox Browser
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
author
Posts: 23958
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Martin Vajsar wrote:
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.



Agreed. Using tail recursion instead of a loop is a really bad thing -- especially since it is a endless loop. Maybe in the future, there will be an optimization that will convert tail recursion to loops, but in the meantime... don't do it.

The other no-no is spin waits. Don't do spin waits. You are eating up precious CPU cycles telling the computer to do nothing useful.

Henry
 
Jigar Naik
Ranch Hand
Posts: 763
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
thanks martin for such detail explanation...

but what is the alternative to avoid the recursive loop ? i am also looking for the alternative. my requirement is like i need to send N # of messages in a second. and if i finish # N no of messages in 100 ms remaining 900 ms the program will remain idle.

and suppose if N = 1000 and my program is able to send only 900 in 1 second remaining 100 messages should be discarded.

What are the alternative ? and which one is the best way ? i can use only J2SE 1.5 API.
 
Martin Vashko
Sheriff
Posts: 3837
66
Netbeans IDE Oracle Firefox Browser
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
To avoid the recursion, use the endless loop as I have already shown you.

However, for this kind of processing you could probably use the java.util.concurrent.ScheduledThreadPoolExecutor class. This class will run your tasks at one second intervals as precisely as your system permits. You'll also no longer need the endless loop. See the documentation of this class.

You will still need to limit the processing of a single batch to under one second. You probably should store the value of System.nanoTime() at the beginning of processing (again, see the documentation) and then check after each message that the elapsed time didn't exceed one second, and break if it did. It would actually be quite similar to the your for-loop in your first post, just add the code for posting a message.

Remember that Java is not a real-time system. Depending on a target platform and various other factors, such as garbage collector, your thread could be preempted in the middle of the processing and might at times process much less messages than would be usual. Nothing can be done to prevent this.

Anyway your requirements seem strange to me. Messages that were not posted within a second would be discarded without further notice? There were not that important after all. Hope you're not building a spam server, there is more than enough of them already...
 
Whose rules are you playing by? This tiny ad doesn't respect those rules:
Gift giving made easy with the permaculture playing cards
https://coderanch.com/t/777758/Gift-giving-easy-permaculture-playing
reply
    Bookmark Topic Watch Topic
  • New Topic