psykeron
psykeron

Reputation: 816

what is a suggested alternative to polling using a while loop

So this is my code that polls for a change in my app's model.

    Thread refreshThread = new Thread(new Runnable() {

        public void run() {

            while(true)
            {                       
                if(TasksManager.isDirty())
                {
                    TasksManager.refreshTasks(true);
                    panel.repaint();
                }
            }
        }
    });
    refreshThread.start();  

Right now it is an immense CPU hog. Here's the breakdown of what happens.

  1. TaskManager realizes that something new has been added.
  2. TaskManager marks itself as dirty.
  3. When my refresh threads finds that its dirty, it immediately performs a refresh on the model and the display panel.
  4. At the end of RefreshTasks(), the model is again marked as clean.

I didn't want the TaskManager to start the refresh since it doesn't hold any reference to the Viewing Panel.

One idea I have is to use a condition.await(). The TaskManager can signal the condition when it has been marked as dirty. But I see that Locks and Conditions go hand in hand. Would it be okay to use a Condition without acquiring a Lock at the beginning of the function?

Upvotes: 1

Views: 3321

Answers (2)

GETah
GETah

Reputation: 21419

You can use wait() and notifyAll() to avoid high CPU usage:

private final Object dirtyLock = new Object();

Thread refreshThread = new Thread(new Runnable() {
    public void run() {
       while(true){
           synchronized(dirtyLock){
               dirtyLock.wait(); // Send this thread to sleep until dirtyLock is unlocked                       
           }
           TasksManager.refreshTasks(true);
           panel.repaint();
        }
    });
refreshThread.start(); 

// When your TaskManager becomes dirty, do the following
public void changeToDirty(){
    TaskManager.setDirty(true);
    synchronized(dirtyLock){
           dirtyLock.notifyAll(); 
           // this will release the refresh thread which will repaint and then go to sleep
     }
}

Upvotes: 5

HXCaine
HXCaine

Reputation: 4258

Why aren't you using listeners for this?

If you have a simple subclass of TasksManager called ContentChangedListener. You can then have the panel.repaint() stuff declared in a listener which is registered with TasksManager from whoever is interested. Many listeners can be registered as required.

In the place of the code which marks TasksManager as dirty, replace it with a loop to notify all listeners of a change.

This solution has the advantage of not requiring another thread or looping.

Upvotes: 4

Related Questions