Title: Threading and Concurrent Programming in Java
1Threading and ConcurrentProgramming in Java
- Threads and Swing
- D.W. Denbo
2Threads and Swing
- The most important thing to remember about using
Swing in a concurrent application is Swing is
not thread-safe!! If you try to manipulate user
interface elements from multiple threads, then
your user interface can become corrupted.
3Outline
- Single Thread Rule
- Exceptions to the rule
- Event dispatching
- A Swing Worker
4SwingThreadTest
5The Single Thread 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. - Realized means that the components paint method
has been or might be called.
6Swing Threads
- In a Swing program, the main method typically
does the following - First it calls a constructor that lays out the
components in a frame window. - Then it invokes the setVisible method on the
frame window. - When the first window is shown, a second thread
is created, the event dispatch thread. All event
notifications, such as calls to actionPerformed
or paintComponent, run in the event dispatch
thread.
7General Rules
- If an action takes a long time, fire up a new
thread to do the work. Otherwise the application
will seem dead. - If an action can block on input or output, use a
new thread. - If you need to wait for a specific amount of
time, use timer events. - Work you do in your threads cant touch the user
interface. Read any UI info before launching
your thread and update UI info from the event
dispatch thread after finishing.
8Exceptions to the Rule
- A few methods are thread-safe In the Swing
documentation, those methods are marked with
This method is thread safe, although most Swing
methods are not. For example - JTextArea
- insert
- append
- replaceRange
- JEditorPane
- replaceSelection
- setText
9- An applications GUI can often be constructed and
shown in the main thread.
public class MyApplication public static void
main(String args) Jframe f new
Jframe(Labels) // Add components to the
frame here... f.pack() f.setVisible(true)
// Dont do any more GUI work here...
10- An applets GUI can be constructed and shown in
the init method. Existing browsers dont draw
the applet until after its init and start methods
have been called. - The following JComponent methods are safe to call
from any thread - repaint
- revalidate
- invalidate
11- Listener list can be modified from any thread
Its always safe to call the addListenerTypeListen
er and removeListenerTypeLister methods. The
add/remove operations have no effect on an event
dispatch thats under way.
12Event Dispatching
- 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 dispatch
thread.
13- Some programs need to perform non-event-driven
GUI work. - Programs that must perform a lengthy
initialization operation before they can be used.
You may want to display a splash screen. The
initialization should not occur in the event
dispatch thread, however, after initialization
the GUI update/change should occur in the
dispatch thread. - Programs whose GUI must be updated as the result
of non-AWT events. For example, suppose a long
operation is running in a separate thread?
Youll want to show progress in the GUI, but
those GUI changes need to be executed in the
dispatch thread.
14- How to run in the event dispatch thread from your
thread? Use either invokeLater or invokeAndWait
methods of EventQueue.
EventQueue.invokeLater(new Runnable() public
void run() label.setText(percentage
complete) )
The invokeLater method returns immediately when
the event is posted to the event queue. The
invokeAndWait method waits until the run method
has completed.
15- A thread that needs access to GUI state...
void printTextField() throws Exception final
String myStrings new String2 Runnable
getTextFields new Runnable() public void
run() myStrings0 textField0.getText()
myStrings1 textField1.getText() Swi
ngUtilities.invokeAndWait(getTextFields) System
.out.println(myStrings0 myStrings1)
16SwingWorker
- SwingWorker does all the dirty work of
implementing a background thread. To use the
SwingWorker class, you first create a subclass of
it. In the subclass, you must implement the
construct() method so that it contains the code
to perform your lengthy operation. You can
optionally implement the finish() method to
execute code on the event dispatch thread after
construct() has finished.
17//OLD CODE public void actionPerformed(ActionEven
t e) ... // ...code that might take a while
to execute ... //BETTER CODE public void
actionPerformed(ActionEvent e) ... final
SwingWorker worker new SwingWorker() public
Object construct() //...code that might take
a while return someValue worker.start(
) // required
18public void actionPerformed(ActionEvent e)
... if(icon null) // havent viewed
before loadImage(imagedir pic.filename,
current) else updatePhotograph(current,
pic) ... // Load an image in a separate
thread. private void loadImage(final String
imagePath, final int index) final SwingWorker
worker new SwingWorker() ImageIcon icon
null public Object construct() icon new
ImageIcon(getURL(imagePath)) return
icon // Runs on the event-dispatching
thread public void finished() Photo pic
(Photo)pictures.elementAt(index) pic.setIcon(i
con) if(index current) updatePhotograph
(index, pic) worker.start()
19Why implement Swing this way?
- Component developers do not have to have an
in-depth understanding of threads programming. - Events are dispatched in a predictable order.
Runnable objects enqueued by invokeLater() are
dispatched from the save event queue as mouse,
keyboard, etc... events. - Less overhead. Time and effort not spent locking
critical areas and synchronizing code.
20