Question

What's the proper way for a Java command line application to do background work without hogging resources? Should it use sleep() in the loop or is there a more elegant/efficient way?

Was it helpful?

Solution

Some heuristics:

  • Don't attempt to make scheduling decisions in your application. The operating system's scheduler is way better than yours will be. Let it do its job.
  • Don't poll if you don't have to. For instance, instead of sleeping n seconds, then waking up to check a non-blocked socket, block on the socket. This second strategy plays better with the operating system's scheduler.
  • Don't use an enormous heap if you don't have to, and try not to allocate enormous chunks of memory at one time. A thrashing application tends to have a negative effect on system performance.
  • Use buffered I/O. Always. If you think you need non-buffered I/O, be absolutely sure you're right. (You're probably wrong.)
  • Don't spawn a lot of threads. Threads are surprisingly expensive; beyond a certain point, more threads will reduce your application's performance profile. If you have lots of work to do concurrently, learn and use java.util.concurrent.

Of course, this is just a starter list...

OTHER TIPS

I'd only use sleep() if there's no work to be done. For example, if you're doing something like polling a task queue periodically and there's nothing there, sleep for a while then check again, etc.

If you're just trying to make sure you don't hog the CPU but you're still doing real work, you could call Thread.yield() periodically. That will relinquish control of the CPU and let other threads run, but it won't put you to sleep. If other processes don't need the CPU you'll get control back and continue to do your work.

You can also set your thread to a low priority: myThread.setPriority(Thread.MIN_PRIORITY);

As Ishmael said, don't do this in your main thread. Create a "worker thread" instead. That way your UI (GUI or CLI) will still be responsive.

There are several ways. I would use ExecutorService... for example:

ExecutorService service = Executors.newCachedThreadPool();

Callable<Result> task = new Callable<Result>() {
    public Result call() throws Exception {
        // code which will be run on background thread
    }
};

Future<Result> future = service.submit(task);

// Next line wait until background task is complete
// without killing CPU. Of course, you can do something
// different here and check your 'future' later.
//
// Note also that future.get() may throw various exceptions too,
// you'll need to handle them properly

Result resultFromBackgroundThread = future.get();

This is Java 5 code, ExecutorService, Callable, Future and similar are in java.util.concurrent package.

One place to start is to make sure that only those resources are being used and no other objects (so that they become garbage collected).

Placing sleep() in a single threading application is only going to halt the current thread. If you're trying to accomplish data being processed in the background while information still needs to be presented to the user then it is best to put the background process in a seperate thread.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top