Sleeping in loops considered harmful

NetBeans gave me an interesting code hint today: Thread.sleep called in loop.

StackOverflow provides some discussion on what’s so dangerous about sleeping, and what we’re supposed to use instead. The hint seems mainly to be aimed at programmers who use a blocking delay in polling loops, allegedly to the detriment of performance. It’s preferable instead to have some service notify the program when input is available.

Of course, sometimes that’s just not practicable (for instance, when input is in the form of a file changed on disk by an external program). But nonetheless, “best practice” demands that we prepare for the future and write it using a executor service. Initially the service does little more than add a lot of boilerplate to an internal implementation of “do task, sleep, repeat”. But it could, ostensibly, in principal, hypothetically, in an ideal world, be changed to one which immediately performed the task in response to the file changing, or which ran multiple tasks in parallel.

So, rather than code like this:

public void run() {
    while (true) {
        processData();

        if (!keepGoing())
            break;

        try {
            Thread.sleep(pollingFrequency);
        } catch (InterruptedException ex) {
            logger.log(Level.SEVERE, "Unexpected exception while sleeping", ex);
        }
    }
}

The “correct” Java code is instead:

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public void run() {
    final ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();

    Runnable processDataCmd = new Runnable() {
        @Override
        public void run() {
            processData();

            if (!keepGoing())
                service.shutdown();
        }
    };

    service.scheduleAtFixedRate(processDataCmd, 0, pollingFrequency, TimeUnit.MILLISECONDS);
}

The second form does have the advantage that the ugly and useless handling of InterruptedException is hidden. Possibly more usefully, it means other code can be run in the meantime, while the service is happily running my task at regular intervals. The problem is that it’s not going to be obvious that the executor is still running; spawning off the polling like this separates it from subsequent code, which is only useful if there is going to be no connection between the two parts.

I’m not altogether sure that it gives a net readability gain in my program.

This entry was posted in Programming and tagged , , . Bookmark the permalink.

5 Responses to Sleeping in loops considered harmful

  1. mortoray says:

    There are APIs to watch for file changes as well and be notified of them. On linux this is the inotify interface. I can’t really think of any useful even which doesn’t have an appropriate way to wait for it without polling.

    • ejrh says:

      There could be Java libraries which do this, using OS-specific native code (inotify on Linux; something else on Windows which I believe has similar functionality). Or I could move the polling loop into a generic PollingExecutorService (hiding it away but not offering any improvement in performance). I just don’t think either of those are worth the complexity, when all I need is a simple loop that processes a file every few seconds.

  2. Pingback: Sleeping in loops considered harmful | Fuat Yazar

  3. rai blaze says:

    I write an app and use while-loop with Thread sleep. Memory increase every loop, performance so poorly. After 4 hours program crashed. After switch to ScheduledExecutorService everything seem better. I still don’t know why while-loop and Thread sleep affect to memory so much like that. But thank you about advice!

  4. Oscar Maximo says:

    I am more a C++ programmer, but: if the event you are waiting is “no more threads with greater or equal priority waiting”, of course Sleep() is better. Notably in case of many processes working together. Let the OS do his job !

Leave a comment