SwingWorker not on Java 6.0
SwingWorker is useful when a time-consuming task has to be performed following a user-interaction event (for example, parsing a huge XML File, on pressing a Button). The most straightforward way to do it is :
private Document doc;
...
JButton button = new JButton("Open XML");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
doc = loadXML();
}
});
This will work, but unfortunately, the loadXML() method will be called in the same thread as the main Swing thread, so if the method needs time to perform, the GUI will freeze during this time.
package com.wsjoung.demo;
import javax.swing.SwingUtilities;
public abstract class SwingWorker {
// see getValue(), setValue()
private Object value;
private Thread thread;
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;
protected synchronized Object getValue() {
return value;
}
private synchronized void setValue(Object x) {
value = x;
}
public abstract Object construct();
public void finished() {
}
public void interrupt() {
Thread t = threadVar.get();
if (t != null) {
t.interrupt();
}
threadVar.clear();
}
public Object get() {
while (true) {
Thread t = threadVar.get();
if (t == null) {
return getValue();
}
try {
t.join();
}
catch (InterruptedException e) {
// propagate
Thread.currentThread().interrupt();
return null;
}
}
}
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();
}
}
public class Task{
public void go() {
current = 0;
final SwingWorker worker = new SwingWorker() {
public Object construct() {
return new ActualTask();
}
};
}
class ActualTask {
ActualTask() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
}
}
}
Task.java
April 24, 2008 at 10:05 am
But SwingWorker IS in Java 6.0.
April 24, 2008 at 10:14 am
Right, it’s in Java6.0 but what if we do not want, and we do not want clients upgrade VM.
April 24, 2008 at 10:58 am
That seems overly complex. Why not just create a Runnable and do SwingUtilities.invokeLater()?
April 25, 2008 at 5:02 am
SwingWorker for Java 1.4 is contributed by SUN :
http://java.sun.com/products/jfc/tsc/articles/threads/src/SwingWorker.java
A much better SwingWorker exists in 1.5 in the SwingLabs API:
http://www.swinglabs.org/
April 26, 2008 at 1:21 am
[...] SwingWorker not on Java 6.0 « {Complexity} [...]