using sleep() for a single thread

别说谁变了你拦得住时间么 提交于 2019-11-25 22:51:20

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

Thread.sleep is a static method. Invocations of it via the reference of any given Thread is simply a form of convenience.

As a result, any invocation of sleep is really calling sleep on the current Thread, which I suspect is the Event Thread in your case. Sleeping/blocking on the Event Thread will give the appearance of being locked up.

If you want the ait thread to sleep, then code that thread to sleep. Designs where one thread "reaches into" another and pushes it around at a low level are fundamentally broken. You write the code for every thread, so write it to do what you want it to do in the first place so you'll find no need to reach into it from the outside.

Which makes more sense, for the person in the kitchen to know how to cook breakfast or the person in the bedroom to yell down and direct them to perform each step of making breakfast? Sure, you might tell them to make breakfast. But you definitely don't direct each step at a low level.

Thread.sleep is a static method which causes the currently executing thread to sleep for the specified amount of time. Java syntax allows you to call a static method via a variable, but the compiler simply uses the compile-time type of that variable to determine which method to call, i.e.

Thread ait = null;
ait.sleep(1000); // calls Thread.sleep(1000), causing current thread to sleep.
                 // In particular, does *not* NPE

You also mentioned wait() - while this is an instance method rather than a static it still causes the current thread to do the waiting (ait.wait(1000) would cause the current thread to wait for up to 1 second or until another thread calls ait.notifyAll()).

There is a Thread.suspend() and its counterpart resume() that were introduced in the very early days of Java to allow one thread to control another, but they were deprecated soon after as they are inherently deadlock-prone. The recommended pattern if you want one thread to "control" another is to do it co-operatively, i.e. have some kind of shared flag that thread A sets and thread B reads, and have B send itself to sleep according to the flag:

volatile boolean threadBShouldRun = true;

// Thread B
while(true) {
  if(threadBShouldRun) {
    // do some stuff
  } else {
    Thread.sleep(1000);
  }
}

// Thread A
if(someCondition) {
  threadBShouldRun = false;
}

but it's generally easier and less error-prone to make use of the facilities that exist in the java.util.concurrent package. Doing multi-threading right is much harder than it appears on the surface.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!