本帖最后由 651012160 于 2013-12-20 13:58 编辑
Swing应用程序员常见的错误是误用Swing事件调度线程(Event DispatchThread,EDT)。他们要么从非UI线程访问UI组件;要么不考虑事件执行顺序;要么不使用独立任务线程而在EDT线程上执行耗时任务,结果使编写的应用程序变得响应迟钝、速度很慢。耗时计算和输入/输出(IO)密集型任务不应放在SwingEDT上运行。发现这种问题的代码并不容易,但Java SE6提供了javax.swing.SwingWorker类,使修正这种代码变得更容易。 使用SwingWorker,程序能启动一个任务线程来异步查询,并马上返回EDT线程,允许EDT继续执行后续的UI事件。
SwingWorker类帮你管理任务线程和EDT之间的交互,尽管SwingWorker不能解决并发线程中遇到的所有问题,但的确有助于分离SwingEDT和任务线程,使它们各负其责:对于EDT来说,就是绘制和更新界面,并响应用户输入;对于任务线程来说,就是执行和界面无直接关系的耗时任务和I/O密集型操作。
SwingWorker结构
SwingWoker实现了java.util.concurrent.RunnableFuture接口。RunnableFuture接口是Runnable和Future两个接口的简单封装。 因为实现了Runnable,所以有run方法,调用FutureTask.run() 因为实现了Future,所以有:
public abstract class SwingWorker<T, V> implements RunnableFuture<T> { //FutureTask
private final FutureTask<T> future;
public final void run() { future.run(); }
public SwingWorker() { Callable<T> callable =
new Callable<T>() {//1. 任务线程一创建就处于PENDING状态
public T call() throws Exception {
//2. 当doInBackground方法开始时,任务线程就进入STARTED状态
setState(StateValue.STARTED);
return doInBackground();
}
};
//FutureTask
future = new FutureTask<T>(callable) {
@Override protected void done() {
doneEDT();
//3. 当doInBackground方法完成后,任务线程就处于DONE状态
setState(StateValue.DONE);
}
}; state = StateValue.PENDING;
propertyChangeSupport = new SwingWorkerPropertyChangeSupport(this);
doProcess = null;
doNotifyProgressChange = null; }}
|