Thread.Sleep在Java中的替代品

Aff*_*tus 6 java swing multithreading jframe thread-sleep

有人告诉我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());
            }
        }
        }
    };
Run Code Online (Sandbox Code Playgroud)

这是共享对象中的同步方法,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();
    } 
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*mes 7

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

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

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


Kon*_*che 4

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

public synchronized void foo()
Run Code Online (Sandbox Code Playgroud)

您可以删除修饰符并使用同步块代替

synchronized (this) {
   // ...
}
Run Code Online (Sandbox Code Playgroud)

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

许多有关 Swing 的线程问题都与事件调度程序线程相关,并且可以使用它轻松解决。我建议你阅读它。

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

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