【发布时间】:2010-03-01 15:04:01
【问题描述】:
我正在尝试在我的应用程序中实现 SwingWorker 类。有没有办法设置SwingWorker“超时”的时间长度?我在想可能会抛出一个我可以捕获然后处理的OutOfTime 异常。我只是不确定如何实现它。
感谢您的帮助!
【问题讨论】:
标签: java swing timeout swingworker
我正在尝试在我的应用程序中实现 SwingWorker 类。有没有办法设置SwingWorker“超时”的时间长度?我在想可能会抛出一个我可以捕获然后处理的OutOfTime 异常。我只是不确定如何实现它。
感谢您的帮助!
【问题讨论】:
标签: java swing timeout swingworker
为什么不将您的任务嵌入到 Runnable 中,将其放入新的单线程 ExecutorService,然后对生成的 Future 执行 get(),并设置适当的超时时间。这将为您提供超时功能,因为如果作业未及时完成,get() 将引发异常。
【讨论】:
简短的回答是“这很难”,具体取决于您的要求。我强烈推荐阅读Java Concurrency In Practice。
您可以做的基本事情是 (a) 确保 SwingWorker 的 Runnable 对中断友好,并且 (b) 设置一个 Timer(或使用 Brian 提到的阻塞 get() 调用)来取消您的 Future。
【讨论】:
内部类 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);
}
}
【讨论】:
java.util.concurrent.TimeoutException 那里。这是故意的吗?
不使用 SwingWorker.get(long, java.util.concurrent.TimeUnit) 的任何特殊原因?它会抛出 TimeoutException,您可以在应用程序中轻松处理。
【讨论】: