Thread.sleep 是如何真正工作的?
Posted
技术标签:
【中文标题】Thread.sleep 是如何真正工作的?【英文标题】:How does Thread.sleep really work? 【发布时间】:2013-03-13 17:05:08 【问题描述】:我编写了一个程序,不时设置按钮的setEnable
。 Thread.sleep()
在另一个类中。代码如下:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Try extends JFrame implements ActionListener
JButton n1 = new JButton("1");
JButton n2 = new JButton("2");
JButton n3 = new JButton("3");
JButton show = new JButton("Show");
show.addActionListener(this);
n1.setEnabled(false);
n2.setEnabled(false);
n3.setEnabled(false);
public Try()
super("Try");
setVisible(true);
setSize(500, 200);
setLayout(new GridLayout(1, 4));
add(n1);
add(n2);
add(n3);
add(show);
public void actionPerformed(ActionEvent a)
Object clicked = a.getSource();
if(show == clicked)
new EasyLevel1().start();
class EasyLevel1 extends Thread
public void run()
try
n1.setEnabled(true);
Thread.sleep(1000);
n1.setEnabled(false);
n2.setEnabled(true);
Thread.sleep(1000);
n2.setEnabled(false);
n3.setEnabled(true);
Thread.sleep(1000);
n3.setEnabled(false);
catch (InterruptedException e)
public static void main(String[] args)
Try frame = new Try();
frame.setVisible(true);
但是,当我把它放在课堂上的actionListener
上时:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Try extends JFrame implements ActionListener
JButton n1 = new JButton("1");
JButton n2 = new JButton("2");
JButton n3 = new JButton("3");
JButton show = new JButton("Show");
show.addActionListener(this);
n1.setEnabled(false);
n2.setEnabled(false);
n3.setEnabled(false);
public Try()
super("Try");
setVisible(true);
setSize(500, 200);
setLayout(new GridLayout(1, 4));
add(n1);
add(n2);
add(n3);
add(show);
public void actionPerformed(ActionEvent a)
Object clicked = a.getSource();
if(show == clicked)
try n1.setEnabled(true);
Thread.sleep(1000);
n1.setEnabled(false);
n2.setEnabled(true);
Thread.sleep(1000);
n2.setEnabled(false);
n3.setEnabled(true);
Thread.sleep(1000);
n3.setEnabled(false);
catch (InterruptedException e)
public static void main(String[] args)
Try frame = new Try();
frame.setVisible(true);
它冻结了我的整个程序,基于该示例,我了解到应该在另一个线程中运行线程睡眠以阻止当前类冻结。但我预计新的 thread.sleep 仍会冻结其操作,就像它仍会执行上面的代码一样,但按钮将响应,因为它位于另一个线程中。但令人惊讶的是,它完成了我想要它做的事情,它并没有像第一个程序那样立即将所有内容都设置为禁用。
【问题讨论】:
【参考方案1】:Thread.sleep()
使当前线程暂停。您在 actionPerformed
中运行它,即在 Swing 事件中。所有 Swing 操作都在单个线程(EDT)中完成。当您使用 Thread.sleep() 暂停它时,Swing 无法处理任何其他事件,因为您还没有从 actionPerformed 侦听器返回。因此,GUI 冻结(不是完整的应用程序,只是 GUI)。
因此,一般来说,在 Swing 事件中执行长时间运行的操作是不好的做法。对于您正在尝试做的事情,最好的选择是使用 Swing 计时器。
【讨论】:
【参考方案2】:发生的情况是,在第二个示例中,Thread.sleep
阻止了EDT
,因此不会发生进一步的 UI 更新。相反,在第一个示例中,您在单独的Thread
中调用sleep
,因此不会发生“冻结”。对于此类任务,首选使用Swing Timers。
【讨论】:
没问题,看看Swing Timers
:)
是的,虽然我选择了 thread.sleep 因为它对我来说更容易,但我目前正在研究你给我的链接以帮助我理解它们。再次感谢【参考方案3】:
Thread.sleep
将导致执行调用的线程休眠指定的时间(或直到线程被中断)。当您在 actionPerformed
方法中调用它时,它会导致 UI 线程休眠。这就是你的程序被锁定的原因。
您应该启动一个单独的线程,该线程将逐步执行您想要在其间睡觉时进行的各种调用。或者(我认为更好)你可以使用Swing timers 来做你想做的事。
【讨论】:
谢谢它在我的脑海中清晰了很多,所以它真的在第二个例子中做我想要的,但是,当线程睡觉时,它也让我的 gui 代码睡觉,所以它“冻结,因为我的 gui 也是睡觉”并在睡眠后变得有反应,因为它不再睡觉。是这样吗? @JerlyTuazon - 没错。如果您使用摇摆计时器来安排各种setEnabled
调用,您的 gui 将不会锁定。
我有一个问题,但它与“冻结”无关,但它涉及 thread.sleep。为什么thread.sleep总是有InterruptedException问题?我的意思是他们已经将其解释为睡眠受到干扰或其他原因。但是我尝试只留下 1 行由线程及其 Thread.sleep 执行,但它仍然显示 InterruptedException,据我所知,我的 thread.sleep 没有过早关闭或受到干扰?
@JerlyTuazon - 有时,在多线程应用程序中,您希望一个线程向另一个线程发出信号,表明它应该停止正在执行的操作。信令线程可以调用另一个线程的interrupt()
方法来做到这一点。应写入另一个线程以检查其中断标志(使用isInterrupted()
)。但是,在它睡觉的时候,它显然不能那样做。但是当调用休眠线程的interrupt()
方法时,sleep()
调用会以InterruptedException
过早退出。这不是一个“问题”——它是一个特性:你刚刚被告知(被程序中的另一个线程)退出。
@JerlyTuazon 在您的特定应用程序中使用这种“中断功能”的一种方法是处理在(当前线程的)级联按钮工作期间用户再次单击“显示”的情况。如果您希望级联“重置”,中断当前线程的工作可能是有意义的,以便您可以在新线程中重新启动它。当然,这更像是一种概念性思维练习;当您迁移到 Swing Timers 时,我相信会有一个计时器停止功能。以上是关于Thread.sleep 是如何真正工作的?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 newman 中设置 setTimeout/Thread.sleep
如何修复调用 Thread.sleep() 时未处理异常的编译错误?
如何在 NetBeans SWING 中的循环中使用 Thread.sleep?