我正在尝试在我的应用程序中实现SwingWorker
类。有没有办法设置一段时间,之后,SwingWorker“超时”?我在想,可能会抛出OutOfTime
异常,我可以抓住然后处理。我只是不确定如何实现它。
感谢您的帮助!
答案 0 :(得分:4)
为什么不将您的任务嵌入Runnable中,将其放入新的单线程ExecutorService,然后在生成的Future上执行get()
并使用适当的超时。这将为您提供超时功能,因为如果作业未及时完成,get()
将抛出异常。
答案 1 :(得分:1)
简短的回答是“很难”,具体取决于您的要求。我强烈建议您阅读Java Concurrency In Practice。
你可以做的基本事情是(a)确保你的SwingWorker的Runnable是中断友好的,并且(b)设置一个Timer(或使用Brian提到的阻塞get()调用来取消你的Future。 / p>
答案 2 :(得分:1)
内部类MySwingWorker可能会满足您的需求:
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);
}
}
答案 3 :(得分:0)
不使用SwingWorker的任何特殊原因。get(long, java.util.concurrent.TimeUnit)?它将抛出您可以在应用程序中轻松处理的TimeoutException。