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