View Javadoc

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