Jerly Tuazon
Jerly Tuazon

Reputation: 13

How does Thread.sleep really work?

I've made a program that sets a button's setEnable from time to time. The Thread.sleep() is in another class. Here's the code:

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);
    }
    }

However, when I put it on my actionListener within the class:

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);
}
}

It freezes my whole program, based from that example I've understood that a thread sleep should be ran in another thread to stop the current class from freezing. But I expected the new thread.sleep with still freeze its operations like it will still do the code above but the buttons will be responsive since its in another thread. But surprisingly it did what I wanted it to do, It didn't instantly set everything to disabled like the first program.

Upvotes: 1

Views: 4233

Answers (3)

Reimeus
Reimeus

Reputation: 159844

What is happening is that in the 2nd example Thread.sleep is blocking the EDT so no further UI updates occur. In contrast, in the first example you are calling sleep in a separare Thread so no "freezing" occurs. For tasks like this the use of Swing Timers is preferred.

Upvotes: 2

Ted Hopp
Ted Hopp

Reputation: 234847

Thread.sleep will cause the thread that executes the call to sleep for the specified time (or until the thread is interrupted). When you call it in the actionPerformed method, it causes the UI thread to sleep. That's why your program is locking up.

You should start a separate thread that will step through the various calls you want to make while sleeping in between. Alternatively (and much better, in my opinion) you could use Swing timers to do what you want.

Upvotes: 2

Cyrille Ka
Cyrille Ka

Reputation: 15533

Thread.sleep() makes the current thread pause. You are running it in an actionPerformed, that is in a Swing Event. All Swing operations are done in a single thread, the EDT. When you pause it with a Thread.sleep(), Swing can not handle any other event because you haven't returned from the actionPerformed listener. Therefore, the GUI freezes (not the complete application, just the GUI).

In general, it is bad practice to do long-running actions in a Swing event because of this. For what you are trying to do, the good alternative is to use Swing timers.

Upvotes: 3

Related Questions