The inner class MySwingWorker may well do what you need:
package com.misc;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class FutureStuffGUI extends JFrame {
/**
* Provides a variant of SwingWorker which operates with a timeout.
*
* @param <T>
*/
private static abstract class MySwingWorker<T> {
private T result;
private Exception raised;
/**
* Constructor.
*
* @param timeout
* @param timeUnit
*/
public MySwingWorker(final long timeout, final TimeUnit timeUnit) {
result = null;
raised = null;
System.out.println(Thread.currentThread().getName() + " starting");
final FutureTask<T> future = new FutureTask<T>(new Callable<T>() {
public T call() throws Exception {
System.out.println(Thread.currentThread().getName() + " running");
T result = doInBackground();
return result;
}
});
System.out.println(Thread.currentThread().getName() + " future: " + future);
final Thread runner = new Thread(null, future, "FutureThread");
Thread watcher = new Thread(null, new Runnable() {
@Override
public void run() {
runner.start();
try {
result = future.get(timeout, timeUnit);
} catch (Exception ex) {
raised = ex;
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
assert SwingUtilities.isEventDispatchThread();
done();
}
});
}
}, "WatcherThread");
watcher.start();
}
/**
* Implement this method as the long-running background task.
*
* @return
* @throws Exception
*/
abstract protected T doInBackground() throws Exception;
/**
* This method is invoked from the UI Event Dispatch Thread on completion or timeout.
*/
abstract protected void done();
/**
* This method should be invoked by the implementation of done() to retrieve
* the result.
*
* @return
* @throws Exception
*/
protected T get() throws Exception {
assert SwingUtilities.isEventDispatchThread();
if (raised != null) {
throw raised;
} else {
return result;
}
}
}
public FutureStuffGUI() {
super("Hello");
init_components();
}
private void init_components() {
JPanel panel = new JPanel();
JButton button = new JButton("Press");
panel.add(button);
add(panel);
pack();
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new MySwingWorker<String>(5, TimeUnit.SECONDS) {
@Override
protected String doInBackground() throws InterruptedException {
assert !SwingUtilities.isEventDispatchThread();
System.out.println(Thread.currentThread().getName() + " doInBackground");
// if (true) { throw new RuntimeException("Blow up"); }
Thread.sleep(6 * 1000);
return "Hello world!";
}
@Override
protected void done() {
assert SwingUtilities.isEventDispatchThread();
String result;
try {
result = get();
System.out.println(Thread.currentThread().getName() + " done; result: " + result);
} catch (Exception ex) {
System.out.println(Thread.currentThread().getName() + " done; errored:");
ex.printStackTrace();
}
}
};
};
});
}
public static void main(String[] args) {
FutureStuffGUI ui = new FutureStuffGUI();
ui.setVisible(true);
}
}