问题
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