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