1 package org.devaki.nextobjects.util;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 import javax.swing.SwingUtilities;
22 /***
23 * This is the 3rd version of SwingWorker (also known as
24 * SwingWorker 3), an abstract class that you subclass to
25 * perform GUI-related work in a dedicated thread. For
26 * instructions on using this class, see:
27 *
28 * http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
29 *
30 * Note that the API changed slightly in the 3rd version:
31 * You must now invoke start() on the SwingWorker after
32 * creating it.
33 * @author <a href="mailto:eflorent@devaki.org">Emmanuel Florent</a>
34 */
35 public abstract class SwingWorker
36 {
37 /*** object value produced by the thread */
38 private Object value;
39 /*** the thread */
40 private Thread thread;
41 /***
42 * Class to maintain reference to current worker thread
43 * under separate synchronization control.
44 */
45 private static class ThreadVar
46 {
47 /*** the thread */
48 private Thread thread;
49 /***
50 * Set the thread
51 * @param t the thread
52 */
53 ThreadVar(final Thread t)
54 {
55 thread = t;
56 }
57 /***
58 * get the thread
59 * @return the thread
60 */
61 final synchronized Thread get()
62 {
63 return thread;
64 }
65 /***
66 * Unset the thread
67 */
68 final synchronized void clear()
69 {
70 thread = null;
71 }
72 }
73 /*** the thread variable */
74 private ThreadVar threadVar;
75 /***
76 * Get the value produced by the worker thread, or null if it
77 * hasn't been constructed yet.
78 * @return object
79 */
80 protected final synchronized Object getValue()
81 {
82 return value;
83 }
84 /***
85 * Set the value produced by worker thread
86 * @param x value
87 */
88 private final synchronized void setValue(final Object x)
89 {
90 value = x;
91 }
92 /***
93 * Compute the value to be returned by the <code>get</code> method.
94 * @return object
95 */
96 public abstract Object construct();
97 /***
98 * Called on the event dispatching thread (not on the worker thread)
99 * after the <code>construct</code> method has returned.
100 */
101 public void finished()
102 {
103 }
104 /***
105 * A new method that interrupts the worker thread. Call this method
106 * to force the worker to stop what it's doing.
107 */
108 public final void interrupt()
109 {
110 Thread t = threadVar.get();
111 if (t != null)
112 {
113 t.interrupt();
114 }
115 threadVar.clear();
116 }
117 /***
118 * Return the value created by the <code>construct</code> method.
119 * Returns null if either the constructing thread or the current
120 * thread was interrupted before a value was produced.
121 *
122 * @return the value created by the <code>construct</code> method
123 */
124 public final Object get()
125 {
126 while (true)
127 {
128 Thread t = threadVar.get();
129 if (t == null)
130 {
131 return getValue();
132 }
133 try
134 {
135 t.join();
136 }
137 catch (InterruptedException e)
138 {
139 Thread.currentThread().interrupt();
140 return null;
141 }
142 }
143 }
144 /***
145 * Start a thread that will call the <code>construct</code> method
146 * and then exit.
147 */
148 public SwingWorker()
149 {
150 final Runnable doFinished = new Runnable()
151 {
152 public final void run()
153 {
154 finished();
155 }
156 };
157 Runnable doConstruct = new Runnable()
158 {
159 public final void run()
160 {
161 try
162 {
163 setValue(construct());
164 }
165 finally
166 {
167 threadVar.clear();
168 }
169 SwingUtilities.invokeLater(doFinished);
170 }
171 };
172 Thread t = new Thread(doConstruct);
173 threadVar = new ThreadVar(t);
174 }
175 /***
176 * Start the worker thread.
177 */
178 public final void start()
179 {
180 Thread t = threadVar.get();
181 if (t != null)
182 {
183 t.start();
184 }
185 }
186 }