| ||||
|
Code - Class EDU.oswego.cs.dl.util.concurrent.misc.SwingWorker1 /* 2 File: SwingWorker.java 3 4 Originally written by Joseph Bowbeer and released into the public domain. 5 This may be used for any purposes whatsoever without acknowledgment. 6 7 Originally part of jozart.swingutils. 8 Adapted for util.concurrent by Joseph Bowbeer. 9 10 */ 11 12 package EDU.oswego.cs.dl.util.concurrent.misc; 13 14 import java.lang.reflect.InvocationTargetException; 15 import javax.swing.SwingUtilities; 16 17 import EDU.oswego.cs.dl.util.concurrent.*; 18 19 /** 20 * An abstract class that you subclass to perform GUI-related work 21 * in a dedicated thread. 22 * <p> 23 * This class was adapted from the SwingWorker written by Hans Muller 24 * and presented in "Using a Swing Worker Thread" in the Swing Connection 25 * - http://java.sun.com/products/jfc/tsc/articles/threads/threads2.html 26 * <p> 27 * A closely related version of this class is described in 28 * "The Last Word in Swing Threads" in the Swing Connection 29 * - http://java.sun.com/products/jfc/tsc/articles/threads/threads3.html 30 * <p> 31 * This SwingWorker is a ThreadFactoryUser and implements Runnable. The 32 * default thread factory creates low-priority worker threads. A special 33 * constructor is provided for enabling a timeout. When the timeout 34 * expires, the worker thread is interrupted. 35 * <p> 36 * Note: Using a timeout of <code>Long.MAX_VALUE</code> will not impose a 37 * timeout but will create an additional thread of control that will respond 38 * to an interrupt even if the <code>construct</code> implementation ignores 39 * them. 40 * <p> 41 * <b>Sample Usage</b> <p> 42 * <pre> 43 * import EDU.oswego.cs.dl.util.concurrent.TimeoutException; 44 * import EDU.oswego.cs.dl.util.concurrent.misc.SwingWorker; 45 * 46 * public class SwingWorkerDemo extends javax.swing.JApplet { 47 * 48 * private static final int TIMEOUT = 5000; // 5 seconds 49 * private javax.swing.JLabel status; 50 * private javax.swing.JButton start; 51 * private SwingWorker worker; 52 * 53 * public SwingWorkerDemo() { 54 * status = new javax.swing.JLabel("Ready"); 55 * status.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); 56 * getContentPane().add(status, java.awt.BorderLayout.CENTER); 57 * start = new javax.swing.JButton("Start"); 58 * getContentPane().add(start, java.awt.BorderLayout.SOUTH); 59 * 60 * start.addActionListener(new java.awt.event.ActionListener() { 61 * public void actionPerformed(java.awt.event.ActionEvent evt) { 62 * if (start.getText().equals("Start")) { 63 * start.setText("Stop"); 64 * status.setText("Working..."); 65 * worker = new DemoSwingWorker(TIMEOUT); 66 * worker.start(); 67 * } else { 68 * worker.interrupt(); 69 * } 70 * } 71 * }); 72 * } 73 * 74 * private class DemoSwingWorker extends SwingWorker { 75 * private static final java.util.Random RAND = new java.util.Random(); 76 * public DemoSwingWorker(long msecs) { 77 * super(msecs); 78 * } 79 * protected Object construct() throws InterruptedException { 80 * // Take a random nap. If we oversleep, the worker times out. 81 * Thread.sleep(RAND.nextInt(2*TIMEOUT)); 82 * return "Success"; 83 * } 84 * protected void finished() { 85 * start.setText("Start"); 86 * try { 87 * Object result = get(); 88 * status.setText((String) result); 89 * } 90 * catch (java.lang.reflect.InvocationTargetException e) { 91 * Throwable ex = e.getTargetException(); 92 * if (ex instanceof TimeoutException) { 93 * status.setText("Timed out."); 94 * } else if (ex instanceof InterruptedException) { 95 * status.setText("Interrupted."); 96 * } else { 97 * status.setText("Exception: " + ex); 98 * } 99 * } 100 * catch (InterruptedException ex) { 101 * // event-dispatch thread won't be interrupted 102 * throw new IllegalStateException(ex+""); 103 * } 104 * } 105 * } 106 * } 107 * </pre> 108 * 109 * @author Joseph Bowbeer 110 * @author Hans Muller 111 * @version 3.0 112 * 113 * <p>[<a HREF="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>] 114 */ 115 public abstract class SwingWorker extends ThreadFactoryUser 116 implements Runnable { 117 118 /** Default thread factory. Creates low priority worker threads. */ 119 private static final ThreadFactory FACTORY = new ThreadFactory() { 120 public Thread newThread(Runnable command) { 121 Thread t = new Thread(command); 122 t.setPriority(Thread.MIN_PRIORITY+1); 123 return t; 124 } 125 }; 126 127 /** Holds the value to be returned by the <code>get</code> method. */ 128 private final FutureResult result = new FutureResult(); 129 130 /** Maximum time to wait for worker to complete. */ 131 private final long timeout; 132 133 /** Worker thread. */ 134 private Thread thread; 135 136 /** Creates new SwingWorker with no timeout. */ 137 public SwingWorker() { 138 this(FACTORY, 0); 139 } 140 141 /** 142 * Creates new SwingWorker with specified timeout. 143 * @param msecs timeout in milliseconds, or <code>0</code> 144 * for no time limit. 145 */ 146 public SwingWorker(long msecs) { 147 this(FACTORY, msecs); 148 } 149 150 /** 151 * Creates new SwingWorker with specified thread factory and timeout. 152 * @param factory factory for worker threads. 153 * @param msecs timeout in milliseconds, or <code>0</code> 154 * for no time limit. 155 */ 156 protected SwingWorker(ThreadFactory factory, long msecs) { 157 setThreadFactory(factory); 158 if (msecs < 0) { 159 throw new IllegalArgumentException("timeout="+msecs); 160 } 161 timeout = msecs; 162 } 163 164 /** 165 * Computes the value to be returned by the <code>get</code> method. 166 */ 167 protected abstract Object construct() throws Exception; 168 169 /** 170 * Called on the event dispatching thread (not on the worker thread) 171 * after the <code>construct</code> method has returned. 172 */ 173 protected void finished() { } 174 175 /** 176 * Returns timeout period in milliseconds. Timeout is the 177 * maximum time to wait for worker to complete. There is 178 * no time limit if timeout is <code>0</code> (default). 179 */ 180 public long getTimeout() { 181 return timeout; 182 } 183 184 /** 185 * Calls the <code>construct</code> method to compute the result, 186 * and then invokes the <code>finished</code> method on the event 187 * dispatch thread. 188 */ 189 public void run() { 190 191 Callable function = new Callable() { 192 public Object call() throws Exception { 193 return construct(); 194 } 195 }; 196 197 Runnable doFinished = new Runnable() { 198 public void run() { 199 finished(); 200 } 201 }; 202 203 /* Convert to TimedCallable if timeout is specified. */ 204 long msecs = getTimeout(); 205 if (msecs != 0) { 206 TimedCallable tc = new TimedCallable(function, msecs); 207 tc.setThreadFactory(getThreadFactory()); 208 function = tc; 209 } 210 211 result.setter(function).run(); 212 SwingUtilities.invokeLater(doFinished); 213 } 214 215 /** 216 * Starts the worker thread. 217 */ 218 public synchronized void start() { 219 if (thread == null) { 220 thread = getThreadFactory().newThread(this); 221 } 222 thread.start(); 223 } 224 225 /** 226 * Stops the worker and sets the exception to InterruptedException. 227 */ 228 public synchronized void interrupt() { 229 if (thread != null) { 230 /* Try-catch is workaround for JDK1.2 applet security bug. 231 On some platforms, a security exception is thrown if an 232 applet interrupts a thread that is no longer alive. */ 233 try { thread.interrupt(); } catch (Exception ex) { } 234 } 235 result.setException(new InterruptedException()); 236 } 237 238 /** 239 * Return the value created by the <code>construct</code> method, 240 * waiting if necessary until it is ready. 241 * 242 * @return the value created by the <code>construct</code> method 243 * @exception InterruptedException if current thread was interrupted 244 * @exception InvocationTargetException if the constructing thread 245 * encountered an exception or was interrupted. 246 */ 247 public Object get() 248 throws InterruptedException, InvocationTargetException { 249 return result.get(); 250 } 251 252 /** 253 * Wait at most msecs to access the constructed result. 254 * @return current value 255 * @exception TimeoutException if not ready after msecs 256 * @exception InterruptedException if current thread has been interrupted 257 * @exception InvocationTargetException if the constructing thread 258 * encountered an exception or was interrupted. 259 */ 260 public Object timedGet(long msecs) 261 throws TimeoutException, InterruptedException, InvocationTargetException { 262 return result.timedGet(msecs); 263 } 264 265 /** 266 * Get the exception, or null if there isn't one (yet). 267 * This does not wait until the worker is ready, so should 268 * ordinarily only be called if you know it is. 269 * @return the exception encountered by the <code>construct</code> 270 * method wrapped in an InvocationTargetException 271 */ 272 public InvocationTargetException getException() { 273 return result.getException(); 274 } 275 276 /** 277 * Return whether the <code>get</code> method is ready to 278 * return a value. 279 * 280 * @return true if a value or exception has been set. else false 281 */ 282 public boolean isReady() { 283 return result.isReady(); 284 } 285 286 } 287 |
|||
Java API By Example, From Geeks To Geeks. |
Conditions of Use |
About Us
© 2002 - 2005, KickJava.com, or its affiliates
|