Thread.sleep如何真正起作用?

时间:2013-03-24 01:18:53

标签: java multithreading swing sleep event-dispatch-thread

我制作了一个不时设置按钮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仍然冻结其操作,就像它仍然会执行上面的代码,但按钮将响应,因为它在另一个线程。但令人惊讶的是它完成了我想要它做的事情,并没有像第一个程序那样立即将所有内容设置为禁用。

3 个答案:

答案 0 :(得分:3)

Thread.sleep()使当前线程暂停。您正在actionPerformed中运行它,即在Swing事件中。所有Swing操作都在一个线程EDT中完成。当您使用Thread.sleep()暂停它时,Swing无法处理任何其他事件,因为您尚未从actionPerformed侦听器返回。因此,GUI冻结(不是完整的应用程序,只是GUI)。

通常,由于这个原因,在Swing事件中执行长时间运行是不好的做法。对于你想要做的事情,最好的选择是使用Swing计时器。

答案 1 :(得分:2)

Thread.sleep将导致执行调用的线程在指定时间内休眠(或直到线程被中断)。当您在actionPerformed方法中调用它时,它会导致UI线程休眠。这就是你的程序锁定的原因。

你应该开始一个单独的线程,它会在你睡觉之间逐步完成你想要进行的各种调用。或者(在我看来更好)你可以使用Swing timers做你想做的事。

答案 2 :(得分:2)

正在发生的事情是,在第二个示例Thread.sleep阻止EDT,因此不会再发生UI更新。相反,在第一个示例中,您在分隔sleep中调用Thread,因此不会发生“冻结”。对于这样的任务,首选使用Swing Timers