/*************************************************** * * cismet GmbH, Saarbruecken, Germany * * ... and it just works. * ****************************************************/ package Sirius.navigator.tools; import javax.swing.SwingUtilities; import de.cismet.tools.CismetThreadPool; /** * This is the 3rd version of SwingWorker (also known as SwingWorker 3), an abstract class that you subclass to perform * GUI-related work in a dedicated thread. For instructions on using this class, see: * * <p>http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html</p> * * <p>Note that the API changed slightly in the 3rd version: You must now invoke start() on the SwingWorker after * creating it.</p> * * @version $Revision$, $Date$ */ public abstract class SwingWorker { //~ Instance fields -------------------------------------------------------- private Object value; // see getValue(), setValue() private Thread thread; private ThreadVar threadVar; //~ Constructors ----------------------------------------------------------- /** * Start a thread that will call the <code>construct</code> method and then exit. */ public SwingWorker() { final Runnable doFinished = new Runnable() { @Override public void run() { finished(); } }; final Runnable doConstruct = new Runnable() { @Override public void run() { try { setValue(construct()); } finally { threadVar.clear(); } SwingUtilities.invokeLater(doFinished); } }; final Thread t = new Thread(doConstruct); threadVar = new ThreadVar(t); } //~ Methods ---------------------------------------------------------------- /** * Get the value produced by the worker thread, or null if it hasn't been constructed yet. * * @return DOCUMENT ME! */ protected synchronized Object getValue() { return value; } /** * Set the value produced by worker thread. * * @param x DOCUMENT ME! */ private synchronized void setValue(final Object x) { value = x; } /** * Compute the value to be returned by the <code>get</code> method. * * @return DOCUMENT ME! */ public abstract Object construct(); /** * Called on the event dispatching thread (not on the worker thread) after the <code>construct</code> method has * returned. */ public void finished() { } /** * A new method that interrupts the worker thread. Call this method to force the worker to stop what it's doing. */ public void interrupt() { final Thread t = threadVar.get(); if (t != null) { t.interrupt(); } threadVar.clear(); } /** * Return the value created by the <code>construct</code> method. Returns null if either the constructing thread or * the current thread was interrupted before a value was produced. * * @return the value created by the <code>construct</code> method */ public Object get() { while (true) { final Thread t = threadVar.get(); if (t == null) { return getValue(); } try { t.join(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); // propagate return null; } } } /** * Start the worker thread. */ public void start() { final Thread t = threadVar.get(); if (t != null) { CismetThreadPool.execute(t); } } //~ Inner Classes ---------------------------------------------------------- /** * Class to maintain reference to current worker thread under separate synchronization control. * * @version $Revision$, $Date$ */ private static class ThreadVar { //~ Instance fields ---------------------------------------------------- private Thread thread; //~ Constructors ------------------------------------------------------- /** * Creates a new ThreadVar object. * * @param t DOCUMENT ME! */ ThreadVar(final Thread t) { thread = t; } //~ Methods ------------------------------------------------------------ /** * DOCUMENT ME! * * @return DOCUMENT ME! */ synchronized Thread get() { return thread; } /** * DOCUMENT ME! */ synchronized void clear() { thread = null; } } } // old /** * An abstract class that you subclass to perform * GUI-related work in a dedicated thread. * For instructions on using this class, see * http://java.sun.com/products/jfc/swingdoc-current/threads2.html */ /*public abstract class SwingWorker { private Object value; // see getValue(), setValue() private Thread thread; /** * Class to maintain reference to current worker thread * under separate synchronization control. */ /*private static class ThreadVar { * private Thread thread; ThreadVar(Thread t) { thread = t; } synchronized Thread get() { return thread; } synchronized * void clear() { thread = null; } } * * private ThreadVar threadVar; * * /** Get the value produced by the worker thread, or null if it hasn't been constructed yet. */ /* protected synchronized Object getValue() { * return value; } * * /** Set the value produced by worker thread */ /* private synchronized void setValue(Object x) { * value = x; } * * /** Compute the value to be returned by the <code>get</code> method. */ /* public abstract Object construct(); * * /** Called on the event dispatching thread (not on the worker thread) after the <code>construct</code> method has * returned. */ /* public void finished() { * } * * /** A new method that interrupts the worker thread. Call this method to force the worker to abort what it's doing. */ /* public void interrupt() { * Thread t = threadVar.get(); if (t != null) { t.interrupt(); } threadVar.clear(); } * * /** Return the value created by the <code>construct</code> method. Returns null if either the constructing thread or * the current thread was interrupted before a value was produced. * * @return the value created by the <code>construct</code> method */ /* public Object get() { * while (true) { Thread t = threadVar.get(); if (t == null) { return getValue(); } try { * t.join(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); // propagate * return null; } } } * * * /** Start a thread that will call the <code>construct</code> method and then exit. */ /* public SwingWorker() { * final Runnable doFinished = new Runnable() { public void run() { finished(); } }; * * Runnable doConstruct = new Runnable() { public void run() { try { setValue(construct()); * } finally { threadVar.clear(); } * * SwingUtilities.invokeLater(doFinished); } }; * * Thread t = new Thread(doConstruct); threadVar = new ThreadVar(t); t.start(); }}*/