简体   繁体   中英

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();
    } 
}

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.

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]

I would make use of monitors: http://www.artima.com/insidejvm/ed2/threadsynch4.html Maybe with notify or notifyAll you can solve it. Good luck!

Always keep your Event Dispatcher Thread (EDT) which is responsible for handling your GUI, away from any Non-UI work. Also, don't synchronize the entire method, but synchronize the atomic statements

synchronized(this){
    //...
}

You can try this following code :

public static void delay(int waitTime) {
        long endTime = System.currentTimeMillis() + (waitTime * 1000);
        while (System.currentTimeMillis() < endTime) {}
    } 

Call as delay(5). And control will wait for 5 seconds.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM