Start of Tutorial > Start of Trail > Start of Lesson |
Search
Feedback Form |
If your program creates and refers to its GUI the right way, you might not need to worry about threads. For example, if your program is an applet, it's safe to construct its GUI in theinit
method. And if your program is an application with the following common pattern, you're also safe:However, if your program creates threads to perform tasks that affect the GUI, or if it manipulates the already-visible GUI in response to anything but a standard event, then read on! If you aren't familiar with threads, you might first want to read Doing Two or More Tasks At Once: Threads -- just for concepts. Don't bother with the details of coding threads, since we give you information about that in How to Use Threads.//Thread-safe example public class MyApplication { public static void main(String[] args) { JFrame f = new JFrame(...); ...//Add components to the frame here... f.pack(); f.setVisible(true); //Don't do any more GUI work here. } ... //All manipulation of the GUI -- setText, getText, etc. -- //is performed in event handlers such as actionPerformed(). ... }
- The Single-Thread Rule
- Swing components can be accessed by only one thread at a time, generally, the event-dispatching thread.
- Exceptions to the Rule
- A few operations are guaranteed to be thread safe.
- How to Execute Code in the Event-Dispatching Thread
- If you need access to the UI from outside event-handling or painting code, you can use the
SwingUtilities
invokeLater
orinvokeAndWait
method.
The single-thread rule is as follows:
Rule: Once a Swing component has been realized, all code that might affect or depend on the state of that component should be executed in the event-dispatching thread.This rule might sound scary, but for many simple programs, you don't have to worry about threads. Before we go into detail about how to write Swing code, let's define the term realized.
Realized means that the component has been painted on-screen, or that it is ready to be painted. A Swing component that's a top-level window is realized by having one of these methods invoked on it:
setVisible(true)
,show
, orpack
. Once a window is realized, all the components that it contains are realized. Another way to realize a component is to add it to a container that's already realized. You'll see examples of realizing components later.
Note: Theshow
method does the same thing assetVisible(true)
.
There are a few exceptions to the rule that all code that might affect a realized Swing component must run in the event-dispatching thread.
- A few methods are thread safe.
- In the Swing API documentation, thread-safe methods are marked with this text:
This method is thread safe, although most Swing methods are not.- An application's GUI can often be constructed and shown in the main thread.
- As long as no components (Swing or otherwise) have been realized in the current runtime environment, it's fine to construct and show a GUI in the main thread of an application. To help you see why, here's an analysis of the thread safety of the thread-safe example. To refresh your memory, here are the important lines from the example:
public static void main(String[] args) { JFrame f = new JFrame(...); ...//Add components to the frame here... f.pack(); f.setVisible(true); //Don't do any more GUI work here. }
- The example constructs the GUI in the main thread. In general, you can construct (but not show) a GUI in any thread, as long as you don't make any calls that refer to or affect already-realized components.
- The components in the GUI are realized by the
pack
call.- Immediately afterward, the components in the GUI are shown with the
setVisible
(orshow
) call. Technically, thesetVisible
call is unsafe because the components have already been realized by thepack
call. However, because the program doesn't already have a visible GUI, it's exceedingly unlikely that a paint request will occur beforesetVisible
returns.- The main thread executes no GUI code after the
setVisible
call. This means that all GUI work moves from the main thread to the event-dispatching thread, and the example is, in practice, thread safe.
- An applet's GUI can be constructed and shown in the
init
method.- Existing browsers don't paint an applet until after its
init
andstart
methods have been called. Thus, constructing the GUI in the applet'sinit
method is safe, as long as you never callshow()
orsetVisible(true)
on the actual applet object.
- Two
JComponent
methods are safe to call from any thread:repaint
andrevalidate
.- These methods queue requests to be executed on the event-dispatching thread.
- Listener lists can be modified from any thread.
- It's always safe to call the
addListenerTypeListener
andremoveListenerTypeListener
methods. The add/remove operations have no effect on an event dispatch that's under way.
Most post-initialization GUI work naturally occurs in the event-dispatching thread. Once the GUI is visible, most programs are driven by events such as button actions or mouse clicks, which are always handled in the event-dispatching thread.However, some programs need to perform non-event-driven GUI work after the GUI is visible. Here are two examples:
- Programs that must perform a lengthy initialization operation before they can be used
- This kind of program should generally show some GUI while the initialization is occurring, and then update or change the GUI. The initialization should not occur in the event-dispatching thread; otherwise, repainting and event dispatch would stop. However, after initialization the GUI update/change should occur in the event-dispatching thread, for thread-safety reasons.
- Programs whose GUI must be updated as the result of nonstandard events
- For example, suppose a server program can get requests from other programs that might be running on different machines. These requests can come at any time, and they result in one of the server's methods being invoked in some possibly unknown thread. How can that method update the GUI? By executing the GUI-update code in the event-dispatching thread.
The
SwingUtilities
class provides two methods to help you run code in the event-dispatching thread:
invokeLater
- Requests that some code be executed in the event-dispatching thread. This method returns immediately, without waiting for the code to execute.
invokeAndWait
- Acts like
invokeLater
, except that this method waits for the code to execute. As a rule, you should useinvokeLater
rather than this method.For information on using
invokeLater
andinvokeAndWait
, and for other tips on writing multithreaded programs, see How to Use Threads.
Start of Tutorial > Start of Trail > Start of Lesson |
Search
Feedback Form |