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?
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.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 callsait.notifyAll()
).There is a
Thread.suspend()
and its counterpartresume()
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: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.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.
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 theSwingUtilities.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 callsleep
while onEvent Dispatch Thread
(or for that matter on the sameThread
) it will wait for the call toThread.sleep
to finish. Now because all Swing events are processed on EDT we pause its execution by callingsleep(..)
thus pausing the UI events from being processed and therefore GUI is frozen (untilsleep(..)
returns).You should not use
Thread.sleep(..)
onEvent Dispatch Thread
(or anyThread
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:
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
andThread
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 inSwingUtilities/EventQueue#invokeXX
block; thats the way things used to be done :PThread.sleep
is a static method. Invocations of it via the reference of any givenThread
is simply a form of convenience.As a result, any invocation of
sleep
is really callingsleep
on the currentThread
, which I suspect is the Event Thread in your case. Sleeping/blocking on the Event Thread will give the appearance of being locked up.