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