为什么 Thread.sleep() 或 TimeUnit.SECONDS.sleep() 会延迟执行先前的语句,而不是从调用 sleep() 的地方暂停

Why does Thread.sleep() or TimeUnit.SECONDS.sleep() delays execution of previous statements instead pausing from where sleep() is called

我在做一件简单的事情,打印一条错误消息,延迟执行 5 秒,然后调用另一个函数,这是代码

public void saveAndDisplay() throws InterruptedException{
//printing error message
if(saveValuesToDatabase()){
        System.out.println("done");
        errorType = "Done, you will be redirected to MainProject";
        String message = "<html><body><font color='red'>"
            + errorType
            + "</font></body></html>";
        lblError.setText(message);
    } else {
        System.out.println("not done");
        errorType = "Some problem occured, try again";
        String message = "<html><body><font color='red'>"
            + errorType
            + "</font></body></html>";
        lblError.setText(message);
    }

 //delaying by 5 seconds
 //Thread.sleep(5000); or
 TimeUnit.SECONDS.sleep(5);

 //now calling another function
 doSomethingElse();
}

不是显示错误消息 - 然后延迟 - 然后调用 doSomethingElse(),执行首先延迟 5 秒,然后显示错误消息,然后调用 doSomethingElse()。 这超出了我的理解,因为据我所知,语句在 java 中逐行执行,那么为什么 Thread.sleep(5000)TimeUnit.SECONDS.sleep(5) 即使没有写在那里也会先执行?

如有任何帮助,我们将不胜感激。

我想你的 lblErrorJLabel.
在那种情况下,标签的值被直接设置,但控制权直到睡眠结束后才返回给 AWT 线程。因此标签不会在屏幕上更新。

尝试使用 SwingUtilities.invokeAndWait()

您的代码可能如下所示:

// Compose message to put in label
// Must be 'final'
final String message = ...;

// Create runnable that sets the label
Runnable label_setter;
label_setter = new Runnable()
{
  @Override
  public void run()
  {
    lblError.setText(message);
  }
};

// Set label within AWT thread and wait for it to finish
SwingUtilities.invokeAndWait(label_setter);

// Now we can wait
Timeunit.SECONDS.sleep(5);

...

也许我错了,但用户 here 似乎遇到了你的问题,这是由于他使用睡眠方法使整个 GUI 处于休眠状态,因此 gui 更新仅在延迟之后发生. (我假设你正在使用 java 秋千)

一个Swing计时器在指定的延迟后触发一个或多个动作事件,建议在处理时使用javax.swing.Timer而不是java.util.concurrent.TimeUnitjava.lang.Threadjava.util.Timer使用 GUI-related 任务,因为 Swing 计时器都共享相同的 pre-existing 计时器线程,并且 GUI-related 任务自动在 event-dispatch 线程上执行。 更多信息 here

这是对我有用的代码

public void saveAndDisplay() throws InterruptedException{
//printing error message
if(saveValuesToDatabase()){
    ...
}
Timer timer = new Timer(5000, new ActionListener() {    
    @Override
    public void actionPerformed(ActionEvent arg0) {
        doSomethingElse();
    }
    });
    timer.setRepeats(false);
    timer.start();
}

我认为问题是因为 Thread.sleep() 延迟了当前线程 event-dispatch thread(EDT),它也处理 GUI-related 任务,这就是为什么 lblError 直到计时器在 5 秒后释放线程才显示。