【问题标题】:Thread.Sleep alternative in JavaJava 中的 Thread.Sleep 替代方案
【发布时间】:2012-07-26 21:15:20
【问题描述】:

有人告诉我,有时使用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();
    } 
}

【问题讨论】:

  • 您一定是导致Event Dispatching Thread 等待。您能否在代码中提供一个小示例,说明如何启动线程以及何时调用 wait()?
  • 看看SwingWorker。另外,请参阅 this answer 了解它的工作原理。
  • @theon 我更新了帖子并添加了部分代码。

标签: java multithreading swing jframe thread-sleep


【解决方案1】:

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

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

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

【讨论】:

  • 我已经在 GUI 中停用了 sleep 命令。同步方法在另一个类中,正如我所说,它是一个共享对象,同时被两个不同的线程使用。
【解决方案2】:

您可以缩小synchronize 语句的范围。例如,如果您正在对整个方法进行同步

public synchronized void foo()

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

synchronized (this) {
   // ...
}

如果可能,将Thread.sleep() 移出此块。只同步那些修改共享数据状态的语句。

很多关于 Swing 的线程问题都与Event Dispatcher Thread 相关,并且可以通过它轻松解决。我建议你阅读它。

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

在持有锁时处于休眠或等待状态。 使用 a 调用 Thread.sleep 持有的锁可以阻止其他线程长时间取得进展 时间,因此是一个潜在的严重的活性危害。打电话 持有两个锁的 Object.wait 或 Condition.await 构成类似 冒险。 [JCIP]

【讨论】:

  • 谢谢,我会阅读关于事件调度线程的文章,如果我有其他问题,我会回复你。
  • @Elham 在您的情况下,我认为 Concurrency in Swing 的整个章节都会有所帮助,因为 EDT 用于更新 Swing 组件,而您的同步问题是关于修改你的模型。
  • 实际上更新部分工作得很好。问题是我想让它在每次更新后等待,以便用户可以看到由线程逐步完成的过程的结果。
  • @Elham 那么障碍在哪里? Thread.sleep 很好,只需将同步范围缩小到您修改状态的那些变量
【解决方案3】:

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

【讨论】:

  • 谢谢,但问题是等待和通知线程在程序中工作得很好。我的问题是我想这样做,以便用户看到 GUI 中的增量表示会变慢。
【解决方案4】:

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

synchronized(this){
    //...
}

【讨论】:

  • 好的,谢谢,但这将如何回答我的问题?!​​
  • 并且在我的同步方法中放入的仅有的三个动作是在这个序列中必须处于相同锁定状态的动作。我不能再缩小范围了。
【解决方案5】:

你可以试试下面的代码:

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

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

【讨论】:

  • 请不要用这个,很乱。另一种方法是使用 java.util.Timer
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 2013-03-10
  • 2013-11-18
相关资源
最近更新 更多