Source Code Cross Referenced for SwingWorker.java in  » 6.0-JDK-Core » swing » javax » swing » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
C# / C Sharp
C# / CSharp Tutorial
ASP.Net
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
PHP
Python
SQL Server / T-SQL
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Core » swing » javax.swing 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004:         *
005:         * This code is free software; you can redistribute it and/or modify it
006:         * under the terms of the GNU General Public License version 2 only, as
007:         * published by the Free Software Foundation.  Sun designates this
008:         * particular file as subject to the "Classpath" exception as provided
009:         * by Sun in the LICENSE file that accompanied this code.
010:         *
011:         * This code is distributed in the hope that it will be useful, but WITHOUT
012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014:         * version 2 for more details (a copy is included in the LICENSE file that
015:         * accompanied this code).
016:         *
017:         * You should have received a copy of the GNU General Public License version
018:         * 2 along with this work; if not, write to the Free Software Foundation,
019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020:         *
021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022:         * CA 95054 USA or visit www.sun.com if you need additional information or
023:         * have any questions.
024:         */
025:        package javax.swing;
026:
027:        import java.beans.PropertyChangeListener;
028:        import java.beans.PropertyChangeSupport;
029:        import java.beans.PropertyChangeEvent;
030:        import java.util.List;
031:        import java.util.ArrayList;
032:        import java.util.Collections;
033:
034:        import java.util.concurrent.*;
035:        import java.util.concurrent.locks.*;
036:
037:        import java.awt.event.*;
038:
039:        import javax.swing.SwingUtilities;
040:
041:        import sun.awt.AppContext;
042:        import sun.swing.AccumulativeRunnable;
043:
044:        /**
045:         * An abstract class to perform lengthy GUI-interacting tasks in a
046:         * dedicated thread.
047:         * 
048:         * <p>
049:         * When writing a multi-threaded application using Swing, there are
050:         * two constraints to keep in mind:
051:         * (refer to 
052:         * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html">
053:         *   How to Use Threads
054:         * </a> for more details):
055:         * <ul>
056:         *   <li> Time-consuming tasks should not be run on the <i>Event
057:         *        Dispatch Thread</i>. Otherwise the application becomes unresponsive.
058:         *   </li>
059:         *   <li> Swing components should be accessed  on the <i>Event
060:         *        Dispatch Thread</i> only.
061:         *   </li>
062:         * </ul>
063:         *
064:         * <p>
065:         *
066:         * <p>
067:         * These constraints mean that a GUI application with time intensive
068:         * computing needs at least two threads:  1) a thread to perform the lengthy
069:         * task and 2) the <i>Event Dispatch Thread</i> (EDT) for all GUI-related
070:         * activities.  This involves inter-thread communication which can be
071:         * tricky to implement.
072:         *
073:         * <p>
074:         * {@code SwingWorker} is designed for situations where you need to have a long 
075:         * running task run in a background thread and provide updates to the UI 
076:         * either when done, or while processing. 
077:         * Subclasses of {@code SwingWorker} must implement 
078:         * the {@link #doInBackground} method to perform the background computation.
079:         *
080:         *
081:         * <p>
082:         * <b>Workflow</b>
083:         * <p>
084:         * There are three threads involved in the life cycle of a 
085:         * {@code SwingWorker} :
086:         * <ul>
087:         * <li>
088:         * <p>
089:         * <i>Current</i> thread: The {@link #execute} method is
090:         * called on this thread. It schedules {@code SwingWorker} for the execution on a
091:         * <i>worker</i>
092:         * thread and returns immediately. One can wait for the {@code SwingWorker} to
093:         * complete using the {@link #get get} methods.
094:         * <li>
095:         * <p>
096:         * <i>Worker</i> thread: The {@link #doInBackground} 
097:         * method is called on this thread.
098:         * This is where all background activities should happen. To notify
099:         * {@code PropertyChangeListeners} about bound properties changes use the
100:         * {@link #firePropertyChange firePropertyChange} and
101:         * {@link #getPropertyChangeSupport} methods. By default there are two bound
102:         * properties available: {@code state} and {@code progress}.
103:         * <li>
104:         * <p>
105:         * <i>Event Dispatch Thread</i>:  All Swing related activities occur
106:         * on this thread. {@code SwingWorker} invokes the
107:         * {@link #process process} and {@link #done} methods and notifies
108:         * any {@code PropertyChangeListeners} on this thread.
109:         * </ul>
110:         * 
111:         * <p>
112:         * Often, the <i>Current</i> thread is the <i>Event Dispatch
113:         * Thread</i>. 
114:         *
115:         *
116:         * <p>
117:         * Before the {@code doInBackground} method is invoked on a <i>worker</i> thread,
118:         * {@code SwingWorker} notifies any {@code PropertyChangeListeners} about the
119:         * {@code state} property change to {@code StateValue.STARTED}.  After the
120:         * {@code doInBackground} method is finished the {@code done} method is
121:         * executed.  Then {@code SwingWorker} notifies any {@code PropertyChangeListeners}
122:         * about the {@code state} property change to {@code StateValue.DONE}.
123:         *
124:         * <p>
125:         * {@code SwingWorker} is only designed to be executed once.  Executing a
126:         * {@code SwingWorker} more than once will not result in invoking the
127:         * {@code doInBackground} method twice.
128:         *
129:         * <p>
130:         * <b>Sample Usage</b>
131:         * <p>
132:         * The following example illustrates the simplest use case.  Some 
133:         * processing is done in the background and when done you update a Swing 
134:         * component.
135:         *
136:         * <p>
137:         * Say we want to find the "Meaning of Life" and display the result in
138:         * a {@code JLabel}.
139:         * 
140:         * <pre>
141:         *   final JLabel label;
142:         *   class MeaningOfLifeFinder extends SwingWorker&lt;String, Object&gt; {
143:         *       {@code @Override}
144:         *       public String doInBackground() {
145:         *           return findTheMeaningOfLife();
146:         *       }
147:         *
148:         *       {@code @Override}
149:         *       protected void done() {
150:         *           try { 
151:         *               label.setText(get());
152:         *           } catch (Exception ignore) {
153:         *           }
154:         *       }
155:         *   }
156:         * 
157:         *   (new MeaningOfLifeFinder()).execute();
158:         * </pre>
159:         * 
160:         * <p>
161:         * The next example is useful in situations where you wish to process data 
162:         * as it is ready on the <i>Event Dispatch Thread</i>.
163:         *
164:         * <p>
165:         * Now we want to find the first N prime numbers and display the results in a
166:         * {@code JTextArea}.  While this is computing, we want to update our
167:         * progress in a {@code JProgressBar}.  Finally, we also want to print 
168:         * the prime numbers to {@code System.out}.
169:         * <pre>
170:         * class PrimeNumbersTask extends 
171:         *         SwingWorker&lt;List&lt;Integer&gt;, Integer&gt; {
172:         *     PrimeNumbersTask(JTextArea textArea, int numbersToFind) { 
173:         *         //initialize 
174:         *     }
175:         *
176:         *     {@code @Override}
177:         *     public List&lt;Integer&gt; doInBackground() {
178:         *         while (! enough &amp;&amp; ! isCancelled()) {
179:         *                 number = nextPrimeNumber();
180:         *                 publish(number);
181:         *                 setProgress(100 * numbers.size() / numbersToFind);
182:         *             }
183:         *         }
184:         *         return numbers;
185:         *     }
186:         *
187:         *     {@code @Override}
188:         *     protected void process(List&lt;Integer&gt; chunks) {
189:         *         for (int number : chunks) {
190:         *             textArea.append(number + &quot;\n&quot;);
191:         *         }
192:         *     }
193:         * }
194:         *
195:         * JTextArea textArea = new JTextArea();
196:         * final JProgressBar progressBar = new JProgressBar(0, 100);
197:         * PrimeNumbersTask task = new PrimeNumbersTask(textArea, N);
198:         * task.addPropertyChangeListener(
199:         *     new PropertyChangeListener() {
200:         *         public  void propertyChange(PropertyChangeEvent evt) {
201:         *             if (&quot;progress&quot;.equals(evt.getPropertyName())) {
202:         *                 progressBar.setValue((Integer)evt.getNewValue());
203:         *             }
204:         *         }
205:         *     });
206:         *
207:         * task.execute();
208:         * System.out.println(task.get()); //prints all prime numbers we have got
209:         * </pre>
210:         * 
211:         * <p>
212:         * Because {@code SwingWorker} implements {@code Runnable}, a
213:         * {@code SwingWorker} can be submitted to an
214:         * {@link java.util.concurrent.Executor} for execution.
215:         *  
216:         * @author Igor Kushnirskiy
217:         * @version 1.14 05/05/07
218:         * 
219:         * @param <T> the result type returned by this {@code SwingWorker's}
220:         *        {@code doInBackground} and {@code get} methods
221:         * @param <V> the type used for carrying out intermediate results by this
222:         *        {@code SwingWorker's} {@code publish} and {@code process} methods
223:         * 
224:         * @since 1.6
225:         */
226:        public abstract class SwingWorker<T, V> implements  RunnableFuture<T> {
227:            /**
228:             * number of worker threads.
229:             */
230:            private static final int MAX_WORKER_THREADS = 10;
231:
232:            /**
233:             * current progress.
234:             */
235:            private volatile int progress;
236:
237:            /**
238:             * current state.
239:             */
240:            private volatile StateValue state;
241:
242:            /**
243:             * everything is run inside this FutureTask. Also it is used as
244:             * a delegatee for the Future API.
245:             */
246:            private final FutureTask<T> future;
247:
248:            /**
249:             * all propertyChangeSupport goes through this.
250:             */
251:            private final PropertyChangeSupport propertyChangeSupport;
252:
253:            /**
254:             * handler for {@code process} mehtod.
255:             */
256:            private AccumulativeRunnable<V> doProcess;
257:
258:            /**
259:             * handler for progress property change notifications.
260:             */
261:            private AccumulativeRunnable<Integer> doNotifyProgressChange;
262:
263:            private final AccumulativeRunnable<Runnable> doSubmit = getDoSubmit();
264:
265:            /**
266:             * Values for the {@code state} bound property.
267:             * @since 1.6
268:             */
269:            public enum StateValue {
270:                /**
271:                 * Initial {@code SwingWorker} state.
272:                 */
273:                PENDING,
274:                /**
275:                 * {@code SwingWorker} is {@code STARTED} 
276:                 * before invoking {@code doInBackground}.
277:                 */
278:                STARTED,
279:
280:                /**
281:                 * {@code SwingWorker} is {@code DONE}
282:                 * after {@code doInBackground} method
283:                 * is finished.
284:                 */
285:                DONE
286:            };
287:
288:            /**
289:             * Constructs this {@code SwingWorker}.
290:             */
291:            public SwingWorker() {
292:                Callable<T> callable = new Callable<T>() {
293:                    public T call() throws Exception {
294:                        setState(StateValue.STARTED);
295:                        return doInBackground();
296:                    }
297:                };
298:
299:                future = new FutureTask<T>(callable) {
300:                    @Override
301:                    protected void done() {
302:                        doneEDT();
303:                        setState(StateValue.DONE);
304:                    }
305:                };
306:
307:                state = StateValue.PENDING;
308:                propertyChangeSupport = new SwingWorkerPropertyChangeSupport(
309:                        this );
310:                doProcess = null;
311:                doNotifyProgressChange = null;
312:            }
313:
314:            /**
315:             * Computes a result, or throws an exception if unable to do so.
316:             *
317:             * <p>
318:             * Note that this method is executed only once.
319:             * 
320:             * <p>
321:             * Note: this method is executed in a background thread.
322:             *  
323:             *
324:             * @return the computed result
325:             * @throws Exception if unable to compute a result
326:             * 
327:             */
328:            protected abstract T doInBackground() throws Exception;
329:
330:            /**
331:             * Sets this {@code Future} to the result of computation unless
332:             * it has been cancelled.
333:             */
334:            public final void run() {
335:                future.run();
336:            }
337:
338:            /**
339:             * Sends data chunks to the {@link #process} method. This method is to be
340:             * used from inside the {@code doInBackground} method to deliver 
341:             * intermediate results
342:             * for processing on the <i>Event Dispatch Thread</i> inside the
343:             * {@code process} method.
344:             * 
345:             * <p>
346:             * Because the {@code process} method is invoked asynchronously on
347:             * the <i>Event Dispatch Thread</i>
348:             * multiple invocations to the {@code publish} method
349:             * might occur before the {@code process} method is executed. For
350:             * performance purposes all these invocations are coalesced into one
351:             * invocation with concatenated arguments.
352:             * 
353:             * <p>
354:             * For example:
355:             * 
356:             * <pre>
357:             * publish(&quot;1&quot;);
358:             * publish(&quot;2&quot;, &quot;3&quot;);
359:             * publish(&quot;4&quot;, &quot;5&quot;, &quot;6&quot;);
360:             * </pre>
361:             * 
362:             * might result in:
363:             * 
364:             * <pre>
365:             * process(&quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;4&quot;, &quot;5&quot;, &quot;6&quot;)
366:             * </pre>
367:             *
368:             * <p>
369:             * <b>Sample Usage</b>. This code snippet loads some tabular data and
370:             * updates {@code DefaultTableModel} with it. Note that it safe to mutate
371:             * the tableModel from inside the {@code process} method because it is 
372:             * invoked on the <i>Event Dispatch Thread</i>.
373:             * 
374:             * <pre>
375:             * class TableSwingWorker extends 
376:             *         SwingWorker&lt;DefaultTableModel, Object[]&gt; {
377:             *     private final DefaultTableModel tableModel;
378:             * 
379:             *     public TableSwingWorker(DefaultTableModel tableModel) {
380:             *         this.tableModel = tableModel;
381:             *     }
382:             * 
383:             *     {@code @Override}
384:             *     protected DefaultTableModel doInBackground() throws Exception {
385:             *         for (Object[] row = loadData(); 
386:             *                  ! isCancelled() &amp;&amp; row != null; 
387:             *                  row = loadData()) {
388:             *             publish((Object[]) row);
389:             *         }
390:             *         return tableModel;
391:             *     }
392:             * 
393:             *     {@code @Override}
394:             *     protected void process(List&lt;Object[]&gt; chunks) {
395:             *         for (Object[] row : chunks) {
396:             *             tableModel.addRow(row);
397:             *         }
398:             *     }
399:             * }
400:             * </pre>
401:             * 
402:             * @param chunks intermediate results to process
403:             * 
404:             * @see #process
405:             * 
406:             */
407:            protected final void publish(V... chunks) {
408:                synchronized (this ) {
409:                    if (doProcess == null) {
410:                        doProcess = new AccumulativeRunnable<V>() {
411:                            @Override
412:                            public void run(List<V> args) {
413:                                process(args);
414:                            }
415:
416:                            @Override
417:                            protected void submit() {
418:                                doSubmit.add(this );
419:                            }
420:                        };
421:                    }
422:                }
423:                doProcess.add(chunks);
424:            }
425:
426:            /**
427:             * Receives data chunks from the {@code publish} method asynchronously on the
428:             * <i>Event Dispatch Thread</i>.
429:             * 
430:             * <p>
431:             * Please refer to the {@link #publish} method for more details.
432:             * 
433:             * @param chunks intermediate results to process
434:             * 
435:             * @see #publish
436:             * 
437:             */
438:            protected void process(List<V> chunks) {
439:            }
440:
441:            /**
442:             * Executed on the <i>Event Dispatch Thread</i> after the {@code doInBackground}
443:             * method is finished. The default
444:             * implementation does nothing. Subclasses may override this method to
445:             * perform completion actions on the <i>Event Dispatch Thread</i>. Note
446:             * that you can query status inside the implementation of this method to
447:             * determine the result of this task or whether this task has been cancelled.
448:             * 
449:             * @see #doInBackground
450:             * @see #isCancelled()
451:             * @see #get
452:             */
453:            protected void done() {
454:            }
455:
456:            /**
457:             * Sets the {@code progress} bound property.
458:             * The value should be from 0 to 100.
459:             *
460:             * <p>
461:             * Because {@code PropertyChangeListener}s are notified asynchronously on
462:             * the <i>Event Dispatch Thread</i> multiple invocations to the
463:             * {@code setProgress} method might occur before any
464:             * {@code PropertyChangeListeners} are invoked. For performance purposes
465:             * all these invocations are coalesced into one invocation with the last
466:             * invocation argument only.
467:             * 
468:             * <p>
469:             * For example, the following invokations:
470:             * 
471:             * <pre>
472:             * setProgress(1);
473:             * setProgress(2);
474:             * setProgress(3);
475:             * </pre>
476:             * 
477:             * might result in a single {@code PropertyChangeListener} notification with
478:             * the value {@code 3}.
479:             * 
480:             * @param progress the progress value to set
481:             * @throws IllegalArgumentException is value not from 0 to 100
482:             */
483:            protected final void setProgress(int progress) {
484:                if (progress < 0 || progress > 100) {
485:                    throw new IllegalArgumentException(
486:                            "the value should be from 0 to 100");
487:                }
488:                if (this .progress == progress) {
489:                    return;
490:                }
491:                int oldProgress = this .progress;
492:                this .progress = progress;
493:                if (!getPropertyChangeSupport().hasListeners("progress")) {
494:                    return;
495:                }
496:                synchronized (this ) {
497:                    if (doNotifyProgressChange == null) {
498:                        doNotifyProgressChange = new AccumulativeRunnable<Integer>() {
499:                            @Override
500:                            public void run(List<Integer> args) {
501:                                firePropertyChange("progress", args.get(0),
502:                                        args.get(args.size() - 1));
503:                            }
504:
505:                            @Override
506:                            protected void submit() {
507:                                doSubmit.add(this );
508:                            }
509:                        };
510:                    }
511:                }
512:                doNotifyProgressChange.add(oldProgress, progress);
513:            }
514:
515:            /**
516:             * Returns the {@code progress} bound property.
517:             * 
518:             * @return the progress bound property.
519:             */
520:            public final int getProgress() {
521:                return progress;
522:            }
523:
524:            /**
525:             * Schedules this {@code SwingWorker} for execution on a <i>worker</i>
526:             * thread. There are a number of <i>worker</i> threads available. In the
527:             * event all <i>worker</i> threads are busy handling other
528:             * {@code SwingWorkers} this {@code SwingWorker} is placed in a waiting
529:             * queue.
530:             *
531:             * <p>
532:             * Note:
533:             * {@code SwingWorker} is only designed to be executed once.  Executing a
534:             * {@code SwingWorker} more than once will not result in invoking the
535:             * {@code doInBackground} method twice.
536:             */
537:            public final void execute() {
538:                getWorkersExecutorService().execute(this );
539:            }
540:
541:            // Future methods START
542:            /**
543:             * {@inheritDoc}
544:             */
545:            public final boolean cancel(boolean mayInterruptIfRunning) {
546:                return future.cancel(mayInterruptIfRunning);
547:            }
548:
549:            /**
550:             * {@inheritDoc}
551:             */
552:            public final boolean isCancelled() {
553:                return future.isCancelled();
554:            }
555:
556:            /**
557:             * {@inheritDoc}
558:             */
559:            public final boolean isDone() {
560:                return future.isDone();
561:            }
562:
563:            /**
564:             * {@inheritDoc}
565:             * <p>
566:             * Note: calling {@code get} on the <i>Event Dispatch Thread</i> blocks
567:             * <i>all</i> events, including repaints, from being processed until this
568:             * {@code SwingWorker} is complete.
569:             * 
570:             * <p>
571:             * When you want the {@code SwingWorker} to block on the <i>Event
572:             * Dispatch Thread</i> we recommend that you use a <i>modal dialog</i>.
573:             *
574:             * <p>
575:             * For example:
576:             * 
577:             * <pre>
578:             * class SwingWorkerCompletionWaiter extends PropertyChangeListener {
579:             *     private JDialog dialog;
580:             * 
581:             *     public SwingWorkerCompletionWaiter(JDialog dialog) {
582:             *         this.dialog = dialog;
583:             *     }
584:             * 
585:             *     public void propertyChange(PropertyChangeEvent event) {
586:             *         if (&quot;state&quot;.equals(event.getPropertyName())
587:             *                 &amp;&amp; SwingWorker.StateValue.DONE == event.getNewValue()) {
588:             *             dialog.setVisible(false);
589:             *             dialog.dispose();
590:             *         }
591:             *     }
592:             * }
593:             * JDialog dialog = new JDialog(owner, true);
594:             * swingWorker.addPropertyChangeListener(
595:             *     new SwingWorkerCompletionWaiter(dialog));
596:             * swingWorker.execute();
597:             * //the dialog will be visible until the SwingWorker is done
598:             * dialog.setVisible(true); 
599:             * </pre>
600:             */
601:            public final T get() throws InterruptedException,
602:                    ExecutionException {
603:                return future.get();
604:            }
605:
606:            /**
607:             * {@inheritDoc}
608:             * <p>
609:             * Please refer to {@link #get} for more details.
610:             */
611:            public final T get(long timeout, TimeUnit unit)
612:                    throws InterruptedException, ExecutionException,
613:                    TimeoutException {
614:                return future.get(timeout, unit);
615:            }
616:
617:            // Future methods END
618:
619:            // PropertyChangeSupports methods START
620:            /**
621:             * Adds a {@code PropertyChangeListener} to the listener list. The listener
622:             * is registered for all properties. The same listener object may be added
623:             * more than once, and will be called as many times as it is added. If
624:             * {@code listener} is {@code null}, no exception is thrown and no action is taken.
625:             * 
626:             * <p>
627:             * Note: This is merely a convenience wrapper. All work is delegated to
628:             * {@code PropertyChangeSupport} from {@link #getPropertyChangeSupport}.
629:             * 
630:             * @param listener the {@code PropertyChangeListener} to be added
631:             */
632:            public final void addPropertyChangeListener(
633:                    PropertyChangeListener listener) {
634:                getPropertyChangeSupport().addPropertyChangeListener(listener);
635:            }
636:
637:            /**
638:             * Removes a {@code PropertyChangeListener} from the listener list. This
639:             * removes a {@code PropertyChangeListener} that was registered for all
640:             * properties. If {@code listener} was added more than once to the same
641:             * event source, it will be notified one less time after being removed. If
642:             * {@code listener} is {@code null}, or was never added, no exception is
643:             * thrown and no action is taken.
644:             * 
645:             * <p>
646:             * Note: This is merely a convenience wrapper. All work is delegated to
647:             * {@code PropertyChangeSupport} from {@link #getPropertyChangeSupport}.
648:             * 
649:             * @param listener the {@code PropertyChangeListener} to be removed
650:             */
651:            public final void removePropertyChangeListener(
652:                    PropertyChangeListener listener) {
653:                getPropertyChangeSupport().removePropertyChangeListener(
654:                        listener);
655:            }
656:
657:            /**
658:             * Reports a bound property update to any registered listeners. No event is
659:             * fired if {@code old} and {@code new} are equal and non-null.
660:             * 
661:             * <p>
662:             * This {@code SwingWorker} will be the source for 
663:             * any generated events.
664:             *
665:             * <p>
666:             * When called off the <i>Event Dispatch Thread</i>
667:             * {@code PropertyChangeListeners} are notified asynchronously on
668:             * the <i>Event Dispatch Thread</i>.
669:             * <p>
670:             * Note: This is merely a convenience wrapper. All work is delegated to
671:             * {@code PropertyChangeSupport} from {@link #getPropertyChangeSupport}.
672:             * 
673:             * 
674:             * @param propertyName the programmatic name of the property that was
675:             *        changed
676:             * @param oldValue the old value of the property
677:             * @param newValue the new value of the property
678:             */
679:            public final void firePropertyChange(String propertyName,
680:                    Object oldValue, Object newValue) {
681:                getPropertyChangeSupport().firePropertyChange(propertyName,
682:                        oldValue, newValue);
683:            }
684:
685:            /**
686:             * Returns the {@code PropertyChangeSupport} for this {@code SwingWorker}. 
687:             * This method is used when flexible access to bound properties support is
688:             * needed.
689:             * <p>
690:             * This {@code SwingWorker} will be the source for 
691:             * any generated events.
692:             * 
693:             * <p>
694:             * Note: The returned {@code PropertyChangeSupport} notifies any
695:             * {@code PropertyChangeListener}s asynchronously on the <i>Event Dispatch
696:             * Thread</i> in the event that {@code firePropertyChange} or
697:             * {@code fireIndexedPropertyChange} are called off the <i>Event Dispatch
698:             * Thread</i>.
699:             * 
700:             * @return {@code PropertyChangeSupport} for this {@code SwingWorker}
701:             */
702:            public final PropertyChangeSupport getPropertyChangeSupport() {
703:                return propertyChangeSupport;
704:            }
705:
706:            // PropertyChangeSupports methods END
707:
708:            /**
709:             * Returns the {@code SwingWorker} state bound property.
710:             * 
711:             * @return the current state
712:             */
713:            public final StateValue getState() {
714:                /*
715:                 * DONE is a speacial case
716:                 * to keep getState and isDone is sync
717:                 */
718:                if (isDone()) {
719:                    return StateValue.DONE;
720:                } else {
721:                    return state;
722:                }
723:            }
724:
725:            /**
726:             * Sets this {@code SwingWorker} state bound property.
727:             * @param the state state to set
728:             */
729:            private void setState(StateValue state) {
730:                StateValue old = this .state;
731:                this .state = state;
732:                firePropertyChange("state", old, state);
733:            }
734:
735:            /**
736:             * Invokes {@code done} on the EDT.
737:             */
738:            private void doneEDT() {
739:                Runnable doDone = new Runnable() {
740:                    public void run() {
741:                        done();
742:                    }
743:                };
744:                if (SwingUtilities.isEventDispatchThread()) {
745:                    doDone.run();
746:                } else {
747:                    doSubmit.add(doDone);
748:                }
749:            }
750:
751:            /**
752:             * returns workersExecutorService.
753:             *
754:             * returns the service stored in the appContext or creates it if
755:             * necessary. If the last one it triggers autoShutdown thread to
756:             * get started.
757:             * 
758:             * @return ExecutorService for the {@code SwingWorkers}
759:             * @see #startAutoShutdownThread
760:             */
761:            private static synchronized ExecutorService getWorkersExecutorService() {
762:                final AppContext appContext = AppContext.getAppContext();
763:                Object obj = appContext.get(SwingWorker.class);
764:                if (obj == null) {
765:                    //this creates non-daemon threads. 
766:                    ThreadFactory threadFactory = new ThreadFactory() {
767:                        final ThreadFactory defaultFactory = Executors
768:                                .defaultThreadFactory();
769:
770:                        public Thread newThread(final Runnable r) {
771:                            Thread thread = defaultFactory.newThread(r);
772:                            thread.setName("SwingWorker-" + thread.getName());
773:                            return thread;
774:                        }
775:                    };
776:
777:                    /*
778:                     * We want a to have no more than MAX_WORKER_THREADS
779:                     * running threads.
780:                     *
781:                     * We want a worker thread to wait no longer than 1 second
782:                     * for new tasks before terminating.
783:                     */
784:                    obj = new ThreadPoolExecutor(0, MAX_WORKER_THREADS, 1L,
785:                            TimeUnit.SECONDS,
786:                            new LinkedBlockingQueue<Runnable>(), threadFactory) {
787:
788:                        private final ReentrantLock pauseLock = new ReentrantLock();
789:                        private final Condition unpaused = pauseLock
790:                                .newCondition();
791:                        private boolean isPaused = false;
792:                        private final ReentrantLock executeLock = new ReentrantLock();
793:
794:                        @Override
795:                        public void execute(Runnable command) {
796:                            /*
797:                             * ThreadPoolExecutor first tries to run task
798:                             * in a corePool. If all threads are busy it
799:                             * tries to add task to the waiting queue. If it
800:                             * fails it run task in maximumPool.
801:                             *
802:                             * We want corePool to be 0 and
803:                             * maximumPool to be MAX_WORKER_THREADS
804:                             * We need to change the order of the execution.
805:                             * First try corePool then try maximumPool
806:                             * pool and only then store to the waiting
807:                             * queue. We can not do that because we would
808:                             * need access to the private methods.
809:                             *
810:                             * Instead we enlarge corePool to
811:                             * MAX_WORKER_THREADS before the execution and
812:                             * shrink it back to 0 after. 
813:                             * It does pretty much what we need.
814:                             *
815:                             * While we changing the corePoolSize we need
816:                             * to stop running worker threads from accepting new
817:                             * tasks.
818:                             */
819:
820:                            //we need atomicity for the execute method.
821:                            executeLock.lock();
822:                            try {
823:
824:                                pauseLock.lock();
825:                                try {
826:                                    isPaused = true;
827:                                } finally {
828:                                    pauseLock.unlock();
829:                                }
830:
831:                                setCorePoolSize(MAX_WORKER_THREADS);
832:                                super .execute(command);
833:                                setCorePoolSize(0);
834:
835:                                pauseLock.lock();
836:                                try {
837:                                    isPaused = false;
838:                                    unpaused.signalAll();
839:                                } finally {
840:                                    pauseLock.unlock();
841:                                }
842:                            } finally {
843:                                executeLock.unlock();
844:                            }
845:                        }
846:
847:                        @Override
848:                        protected void afterExecute(Runnable r, Throwable t) {
849:                            super .afterExecute(r, t);
850:                            pauseLock.lock();
851:                            try {
852:                                while (isPaused) {
853:                                    unpaused.await();
854:                                }
855:                            } catch (InterruptedException ignore) {
856:
857:                            } finally {
858:                                pauseLock.unlock();
859:                            }
860:                        }
861:                    };
862:                    appContext.put(SwingWorker.class, obj);
863:                }
864:                return (ExecutorService) obj;
865:            }
866:
867:            private static final Object DO_SUBMIT_KEY = new StringBuilder(
868:                    "doSubmit");
869:
870:            private static AccumulativeRunnable<Runnable> getDoSubmit() {
871:                synchronized (DO_SUBMIT_KEY) {
872:                    final AppContext appContext = AppContext.getAppContext();
873:                    Object doSubmit = appContext.get(DO_SUBMIT_KEY);
874:                    if (doSubmit == null) {
875:                        doSubmit = new DoSubmitAccumulativeRunnable();
876:                        appContext.put(DO_SUBMIT_KEY, doSubmit);
877:                    }
878:                    return (AccumulativeRunnable<Runnable>) doSubmit;
879:                }
880:            }
881:
882:            private static class DoSubmitAccumulativeRunnable extends
883:                    AccumulativeRunnable<Runnable> implements  ActionListener {
884:                private final static int DELAY = (int) (1000 / 30);
885:
886:                @Override
887:                protected void run(List<Runnable> args) {
888:                    for (Runnable runnable : args) {
889:                        runnable.run();
890:                    }
891:                }
892:
893:                @Override
894:                protected void submit() {
895:                    Timer timer = new Timer(DELAY, this );
896:                    timer.setRepeats(false);
897:                    timer.start();
898:                }
899:
900:                public void actionPerformed(ActionEvent event) {
901:                    run();
902:                }
903:            }
904:
905:            private class SwingWorkerPropertyChangeSupport extends
906:                    PropertyChangeSupport {
907:                SwingWorkerPropertyChangeSupport(Object source) {
908:                    super (source);
909:                }
910:
911:                @Override
912:                public void firePropertyChange(final PropertyChangeEvent evt) {
913:                    if (SwingUtilities.isEventDispatchThread()) {
914:                        super .firePropertyChange(evt);
915:                    } else {
916:                        doSubmit.add(new Runnable() {
917:                            public void run() {
918:                                SwingWorkerPropertyChangeSupport.this
919:                                        .firePropertyChange(evt);
920:                            }
921:                        });
922:                    }
923:                }
924:            }
925:        }
w__w_w.j__a_v___a2s._com___ | Contact Us
Copyright 2003 - 08 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.