You are on page 1of 23

Swing and Threads

SwingUtilities

SwingWorker

MySwingWorker

IOC

Threads - 2
Radu Nicolescu Department of Computer Science University of Auckland

1 October 2010

1 / 23

Swing and Threads

SwingUtilities

SwingWorker

MySwingWorker

IOC

Swing and Threads SwingUtilities SwingWorker MySwingWorker IOC

2 / 23

Swing and Threads

SwingUtilities

SwingWorker

MySwingWorker

IOC

Swing specic threads


Initial thread: the thread that starts the main() Event-dispatch thread (EDT, aka GUI thread): executes

drawing and event handling code - should not run time-consuming tasks
Worker (background) threads: for time consuming tasks -

must not interact directly with the GUI


Two high-level solutions for the proper interaction with the

GUI thread
Using SwingUtilities Using SwingWorker

3 / 23

Swing and Threads

SwingUtilities

SwingWorker

MySwingWorker

IOC

SwingUtilities.invokeLater(runnable-task)
sometimes invoked by the initial thread, to properly create and

start the GUI, if other statements follow (in the initial thread)
typically invoked from a worker thread schedules a given task to be asynchronously executed by the

even-dispatch thread and returns immediately (without waiting the actual execution) S w i n g U t i l i t i e s . i n v o k e L a t e r ( new R u n n a b l e ( ) ) { public void run ( ) { // this code will be executed by the event-dispatch thread, // e.g., to update the GUI } });
4 / 23

Swing and Threads

SwingUtilities

SwingWorker

MySwingWorker

IOC

SwingUtilities.invokeAndWait(runnable-task)

invokeAndWait() is similar to invokeLater(), but synchronous,

i.e., the calling thread waits until the event-dispatch thread completes the given task

5 / 23

Swing and Threads

SwingUtilities

SwingWorker

MySwingWorker

IOC

SwingWorker

SwingWorker is a class with two faces http://www.google.com/images?q=janus+images A SwingWorker encapsulates:


one method, doInBackground(), which denes the task that

needs to run by an automatically assigned background thread (no need to create this)
two methods, process() and done(), which will be

automatically executed by the GUI thread (at proper times)

6 / 23

Swing and Threads

SwingUtilities

SwingWorker

MySwingWorker

IOC

SwingWorker

the doInBackground() method will return a nal result, and,

optionally, publishes, item by item, a sequence of interim objects


the GUI process() and done() methods are provided to display

the nal result of doInBackground() and the sequence of its published interim objects (if any) To eectively use SwingWorker, you need to subclass it, and override the above three methods

7 / 23

Swing and Threads

SwingUtilities

SwingWorker

MySwingWorker

IOC

SwingWorker

Additionally, a SwingWorker can use two methods that help transfer objects from the background thread to the GUI thread (with no further user intervention):
one method, publish(), which transfers interim objects from

doInBackground() to process()
one methods, get(), typically run in done(), which picks up

the nal object created by doInBackground() Attention, these two methods are nal, i.e. not overridable

8 / 23

Swing and Threads

SwingUtilities

SwingWorker

MySwingWorker

IOC

SwingWorker

SwingWorker is a generic predened type, SwingWorker<T,V>, where:


T is the type of the nal result of doInBackground() and

picked by get()
V is the type of the interim objects published by

doInBackground() further transferred to process()

9 / 23

Swing and Threads

SwingUtilities

SwingWorker

MySwingWorker

IOC

SwingWorker birds eye view


c l a s s MySwingWorker extends SwingWorker<T , V> { @Override p u b l i c T d o I n B a c k g r o u n d ( ) // background thread // optionally, calls super . p u b l i s h (V) , repeatedly // nally, returns a T @Override p r o t e c t e d v o i d p r o c e s s ( L i s t <V>) // GUI thread // gets lists of Vs, published by d o I n B a c k g r o u n d ( ) @Override p r o t e c t e d v o i d done ( ) // GUI thread // typically, calls super . Get ( ) // to pick the nal T, returned by d o I n B a c k g r o u n d ( ) }
10 / 23

Swing and Threads

SwingUtilities

SwingWorker

MySwingWorker

IOC

MySwingWorker example
As an example, consider a class MySwingWorker<T,V>, where:
T = Double, V = Integer doInBackground() generates a sequence of Integers, say 0, 1,

2, . . . , 20
doInBackground() publishes these Integers as interim values,

to process()
nally, doInBackground() returns an average Double, here

10.0
the GUI thread displays all interim and nal values the GUI must remain responsive at all times, even if the

background process takes a long time to complete


11 / 23

Swing and Threads

SwingUtilities

SwingWorker

MySwingWorker

IOC

MySwingWorker example the GUI

Controls: button BoredButton, button SwingWorker, textarea TextBox


12 / 23

Swing and Threads

SwingUtilities

SwingWorker

MySwingWorker

IOC

MySwingWorker example the GUI

button WorkerButton: starts the background execution of a

MySwingWorker, disables the button and returns immediately (to keep the GUI responsive)
button BoredButton: prints Wait!, to indicate that the GUI

is NOT frozen (even if MySwingWorker is executing in the background)


textarea TextBox: displays results from MySwingWorker

(interim and nal) and texts printed via BoredButton


13 / 23

Swing and Threads

SwingUtilities

SwingWorker

MySwingWorker

IOC

MySwingWorker example overall structure


c l a s s MySwingWorker extends SwingWorker<Double , I n t e g e r > { @Override p u b l i c Double d o I n B a c k g r o u n d ( ) { . . . } @Override p r o t e c t e d v o i d p r o c e s s ( L i s t <I n t e g e r >) { . . . } @Override p r o t e c t e d v o i d done ( ) { . . . } }

14 / 23

Swing and Threads

SwingUtilities

SwingWorker

MySwingWorker

IOC

MySwingWorker example doInBackground()


p u b l i c Double d o I n B a c k g r o u n d ( ) { Double avg = 0 . 0 ; int k = 0; f o r ( i n t i =0; i <=20; i ++) { super . p u b l i s h ( new I n t e g e r ( i ) ) ; k += 1 ; avg += i ; // for illustration purposes only, we can group // the published numbers, 0, 1, 2, . . . , 20, // by inserting here a sleep period see next slide } r e t u r n avg / k ; }
15 / 23

Swing and Threads

SwingUtilities

SwingWorker

MySwingWorker

IOC

MySwingWorker example doInBackground()

p u b l i c Double d o I n B a c k g r o u n d ( ) { ... // this articial sleep favours that published numbers // are grouped together into lists of three try { i f ( i %3==0) Thread . s l e e p ( 1 0 0 0 ) ; } catch ( I n t e r r u p t e d E x c e p t i o n ex ) { ; } ... }

16 / 23

Swing and Threads

SwingUtilities

SwingWorker

MySwingWorker

IOC

MySwingWorker example process()

@Override p r o t e c t e d v o i d p r o c e s s ( L i s t <I n t e g e r >){//GUI thread TraceBox . append ( . . . p r o c e s s : ) ; f o r ( I n t e g e r i : numbers ) { TraceBox . append ( i+ ) ; } TraceBox . append ( \ r \n ) ; }

17 / 23

Swing and Threads

SwingUtilities

SwingWorker

MySwingWorker

IOC

MySwingWorker example done()


@Override p r o t e c t e d v o i d done ( ) { // GUI thread Double avg = 0 . 0 ; try { avg = t h i s . g e t ( ) ; } catch ( I n t e r r u p t e d E x c e p t i o n ex ) { ; } catch ( E x e c u t i o n E x c e p t i o n ex ) { ; } TraceBox . append ( . . . done : avg=+avg+\ r \n ) ; WorkerButton . s e t E n a b l e d ( t r u e ) ; }
18 / 23

Swing and Threads

SwingUtilities

SwingWorker

MySwingWorker

IOC

MySwingWorker example WorkerButton handler

A click on WorkerButton starts the background execution of a MySwingWorker, disables the button and returns immediately (to keep the GUI responsive): p u b l i c v o i d W o r k e r B u t t o n C l i c k ( ) { // GUI thread MySwingWorker msw = new MySwingWorker ( ) ; msw . e x e c u t e ( ) ; WorkerButton . s e t E n a b l e d ( f a l s e ) ; }

19 / 23

Swing and Threads

SwingUtilities

SwingWorker

MySwingWorker

IOC

MySwingWorker example BoredButton handler

A click on BoredButton prints something, to indicate that the GUI is NOT frozen (even if MySwingWorker is executing in the background): p u b l i c v o i d B o r e d B u t t o n C l i c k ( ) { // GUI thread TraceBox . append ( w a i t ! \ r \n ) ; }

20 / 23

Swing and Threads

SwingUtilities

SwingWorker

MySwingWorker

IOC

Inversion of Control (IOC)

There is a bit of magic, in SwingWorker, this class with two faces


you dene the methods process() and done(), but you do not invoke them (not directly) the infrastructure will schedule their execution, in the GUI

thread (as appropriate) This is a nice example of an interesting design pattern, called IOC (Inversion of Control)

21 / 23

Swing and Threads

SwingUtilities

SwingWorker

MySwingWorker

IOC

Inversion of Control (IOC)

Normally
either we call methods already created by others (library

methods)
or we call methods created by ourselves

In the IOC pattern, the library calls our methods


we create methods that we do not ourselves call (not directly) the existing infrastructure (library) will automatically call our

methods, as appropriate

22 / 23

Swing and Threads

SwingUtilities

SwingWorker

MySwingWorker

IOC

SwingWorker get() exceptions


get() is blocking call the caller waits until doInBackground()

terminates
you need not worry about this, if you call get() in the done()

method
however, in general, a waiting get() caller can be interrupted,

i.e. can receive an InterruptedException


a waiting get() caller can receive an indication that

doInBackground() terminated abnormally, via an ExecutionException


the ExecutionException can be further investigated (but we

dont follow this issue here)


23 / 23

You might also like