6

有人告诉我Thread.Sleep(),有时使用是一个糟糕的解决方案,人们希望在同步方法中的动作循环中设置一些时间间隔。

另一方面,我有两个不同的线程,它们在我的程序运行期间处于活动状态,还有一个共享对象,当我在该共享对象中使用 Object.wait(long) 时,它会导致我的 GUI 冻结一段时间。

对于这个问题有什么更好的解决方案?


更新这部分代码包括在 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());
            }
        }
        }
    };

这是共享对象 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();
    } 
}
4

5 回答 5

7

不要在同步方法中睡觉!不要在 GUI 事件处理程序/方法中等待!

拆分同步操作,以便在 GUI 线程上下文中不调用 Sleep() 调用。

也许使用 InvokeLater() 作为第二位。

于 2012-07-28T11:35:12.813 回答
4

您可以缩小synchronize声明的范围。例如,如果您正在同步整个方法

public synchronized void foo()

您可以删除修饰符并改用同步块

synchronized (this) {
   // ...
}

如果可能的话,移动Thread.sleep()这个块的外部。仅同步那些修改共享数据状态的语句。

很多关于 Swing 的线程问题都与Event Dispatcher Thread相关,并且可以很容易地用它来解决。我建议你阅读它。

一点背景知识,为什么不应该Thread.sleep()在同步块内调用:

拿着锁睡觉或等待。在持有锁的情况下调用 Thread.sleep 会导致其他线程长时间无法取得进展,因此存在潜在的严重活性危害。在持有两个锁的情况下调用 Object.wait 或 Condition.await 会带来类似的危险。[JCIP]

于 2012-07-28T11:33:36.140 回答
0

我会使用监视器:http ://www.artima.com/insidejvm/ed2/threadsynch4.html 也许用 notify 或 notifyAll 你可以解决它。祝你好运!

于 2012-07-28T11:39:23.717 回答
0

始终让负责处理 GUI 的事件调度程序线程 (EDT) 远离任何非 UI 工作。另外,不要同步整个方法,而是同步原子语句

synchronized(this){
    //...
}
于 2012-07-28T16:17:31.440 回答
-2

您可以尝试以下代码:

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

调用延迟(5)。控制将等待 5 秒。

于 2014-09-20T15:53:01.940 回答