Thread.Sleep alternative in Java

蓝咒 提交于 2020-01-03 10:57:54

问题


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

回答1:


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.




回答2:


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]




回答3:


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!




回答4:


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){
    //...
}



回答5:


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.



来源:https://stackoverflow.com/questions/11700571/thread-sleep-alternative-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!