Beruflich Dokumente
Kultur Dokumente
SwingUtilities
SwingWorker
MySwingWorker
IOC
Threads - 2
Radu Nicolescu Department of Computer Science University of Auckland
1 October 2010
1 / 23
SwingUtilities
SwingWorker
MySwingWorker
IOC
2 / 23
SwingUtilities
SwingWorker
MySwingWorker
IOC
drawing and event handling code - should not run time-consuming tasks
Worker (background) threads: for time consuming tasks -
GUI thread
Using SwingUtilities Using SwingWorker
3 / 23
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
SwingUtilities
SwingWorker
MySwingWorker
IOC
SwingUtilities.invokeAndWait(runnable-task)
i.e., the calling thread waits until the event-dispatch thread completes the given task
5 / 23
SwingUtilities
SwingWorker
MySwingWorker
IOC
SwingWorker
needs to run by an automatically assigned background thread (no need to create this)
two methods, process() and done(), which will be
6 / 23
SwingUtilities
SwingWorker
MySwingWorker
IOC
SwingWorker
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
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
SwingUtilities
SwingWorker
MySwingWorker
IOC
SwingWorker
picked by get()
V is the type of the interim objects published by
9 / 23
SwingUtilities
SwingWorker
MySwingWorker
IOC
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
SwingUtilities
SwingWorker
MySwingWorker
IOC
SwingUtilities
SwingWorker
MySwingWorker
IOC
MySwingWorker, disables the button and returns immediately (to keep the GUI responsive)
button BoredButton: prints Wait!, to indicate that the GUI
SwingUtilities
SwingWorker
MySwingWorker
IOC
14 / 23
SwingUtilities
SwingWorker
MySwingWorker
IOC
SwingUtilities
SwingWorker
MySwingWorker
IOC
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
SwingUtilities
SwingWorker
MySwingWorker
IOC
@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
SwingUtilities
SwingWorker
MySwingWorker
IOC
SwingUtilities
SwingWorker
MySwingWorker
IOC
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
SwingUtilities
SwingWorker
MySwingWorker
IOC
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
SwingUtilities
SwingWorker
MySwingWorker
IOC
thread (as appropriate) This is a nice example of an interesting design pattern, called IOC (Inversion of Control)
21 / 23
SwingUtilities
SwingWorker
MySwingWorker
IOC
Normally
either we call methods already created by others (library
methods)
or we call methods created by ourselves
methods, as appropriate
22 / 23
SwingUtilities
SwingWorker
MySwingWorker
IOC
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,