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