using sleep() for a single thread

Harper picture Harper · Dec 28, 2012 · Viewed 6.9k times · Source

I am fairly new to java, and am starting to get into using different threads in order to use wait() or sleep() on one part of my code and have the others still run.

For this project, I am using JFrame with the javax.swing.* and java.awt.* imports. What I am trying to do is have one of the threads (in my code it is the main, starting thread) allow the player to choose a space on the tic tac toe board, and when they click it, it will change icons, and then the AI will wait for 1 second before playing back from the second thread that I created.

Unfortunately, whenever I call ait.sleep(1000) (ait is my thread name) both threads wait for 1 second before finishing their execution. Can anyone tell me why sleeping one thread is stopping my whole execution?

Answer

David Kroukamp picture David Kroukamp · Dec 28, 2012

Can anyone tell me why sleeping one thread is stopping my whole execution

to better explain your Swing GUI is created on its own special thread separate from that which main() and other code will run in, this is done via creating your Swing components in the SwingUtilities.invokeXXX block (even if you have not done this your GUI will be run on a single thread called the initial thread) . Now if you simply call sleep while on Event Dispatch Thread (or for that matter on the same Thread) it will wait for the call to Thread.sleep to finish. Now because all Swing events are processed on EDT we pause its execution by calling sleep(..) thus pausing the UI events from being processed and therefore GUI is frozen (until sleep(..) returns).

You should not use Thread.sleep(..) on Event Dispatch Thread (or any Thread where sleep will cuase unwanted execution blocking), as this will cause the UI to seem frozen.

Here is a nice example which demonstrates exactly, this unwanted behavior caused by invoking Thread.sleep(..) on GUI's EDT.

Rather use:

  • Swing Timer for example:

    int delay=1000;// wait for second
    
    Timer timer = new Timer(delay, new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            //action that you want performed 
        }
    });
    //timer.setRepeats(false);//the timer should only go off once
    timer.start();
    
  • Swing Worker

or if no Swing components are being created/modified:

  • TimerTask

  • Thread, you would then use Thread.sleep(int milis) (but thats last option in any case IMO)

UPDATE

Swing Timer/SwingWorker was only added in Java 1.6, however, TimerTask and Thread have been around for alot longer sine Java 1.3 and JDK 1 repsectively, thus you could even use either of the 2 above methods and wrap calls that create/manipulate Swing components in SwingUtilities/EventQueue#invokeXX block; thats the way things used to be done :P