Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thread.Sleep alternative in Java

I've been told that using Thread.Sleep() is a bad solution at times that one would want to make some time interval within a loop of actions in a synchronized method.

On the other hand, I have two different threads which are active throughout the running time of my program and also one shared object and when I use Object.wait(long) in that shared object, it causes my GUI to freeze for some time.

what would be a better solution for this problem?


Update This portion of the code is including one of the threads which is starting in GUI:

class temperatureUp extends Thread 
    {
        @Override
        public void run()
        {
        while(true)
        {
            try
            {
                GBC.increaseTemp();
                updateSystemStatus();
            }
            catch(Exception ex)
            {
                StringWriter w = new StringWriter();
                ex.printStackTrace(new PrintWriter(w));
                txtLog.setText(w + "\n" + txtLog.getText());
            }
        }
        }
    };

and this is the synchronized method in shared object, GBC:

public synchronized void increaseTemp() throws InterruptedException{
    // don't increase the temperature if the boiler 
    // is not turned on...
    while (!isBoilerOn) 
        wait(); 

    // increase the current temperature 
    if ((currentTemp + 1) < MAX_TEMP && currentTemp < desiredTemp) {
        Thread.sleep(2000); ///what should put here if not thread sleep?
        currentTemp ++;    
        updateGasBoilerStatus();
    } 
}
like image 844
Afflatus Avatar asked Jul 28 '12 11:07

Afflatus


2 Answers

Don't sleep inside the synchronized method! Don't wait in GUI event handlers/methods!

Split up the sychronized actions so that the Sleep() call is not called in the GUI thread context.

Maybe use use InvokeLater() for the second bit.

like image 167
Martin James Avatar answered Sep 19 '22 16:09

Martin James


You could shrink the scope of the synchronize statement. For instance if you are synchronizing on the whole method

public synchronized void foo()

You could remove the modifier and use a synchronized block instead

synchronized (this) {
   // ...
}

and move the Thread.sleep() outside of this block if possible. Only synchronize on those statements which modify states of shared data.

A lot of threading problems regarding Swing are related to the Event Dispatcher Thread and can be easily solved with it. I recommend you read into it.

A little bit background, why you shouldn't call Thread.sleep() inside a synchronization block:

Sleeping or waiting while holding a lock. Calling Thread.sleep with a lock held can prevent other threads from making progress for a long time and is therefore a potentially serious liveness hazard. Calling Object.wait or Condition.await with two locks held poses a similar hazard. [JCIP]

like image 41
Konrad Reiche Avatar answered Sep 17 '22 16:09

Konrad Reiche