View Javadoc

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