SwingWorker解析
一 线程类别及为什么要使用SwingWorker
初始线程:在标准的程序中,只有一个这样的线程:这个线程将调用程序主类中的main方法。在Swing程序中,初始线程主要作用是创建GUI,通过EventQueue的invokeLater方法或者invokeAndWait方法
EventQueue.invokeLater(newRunnable()) {
publicvoidrun() {
createAndShowGUI();
}}
事件分派线程(Event dipatch thread EDT):根据单一线程规则,所有的接触Swing组件的代码必须在该线程执行。在该线程执行的事件必须是要能快速完成的,否则事件堆积起来将造成界面响应过慢。
工作线程:通常执行所有消耗时间的任务。
这些约束意味着需要耗时操作的 GUI 应用程序至少需要以下两个线程:
1) 执行长时间任务的工作线程;
2) 所有 GUI 相关活动的事件指派线程 (EDT)这涉及到难以实现的线程间通信。
SwingWorker 设计用于需要在后台线程中运行长时间运行任务的情况,并可在完成后或者在处理过程中向 UI 提供更新。SwingWorker 的子类必须实现 doInBackground() 方法,以执行后台计算。(当然也可以采用启动新线程完成耗时任务,但此时应该在线程中使用EventQueue.invokeLater方法来更新用户界面,步骤较为繁琐)
二 使用SwingWorker
2.1 后台任务的典型UI活动:
1)工作过程中更新UI显示进度
2)工作完成后做最后的更新
工作流
SwingWorker 的生命周期中包含三个线程:
当前线程:在此线程上调用 execute() 方法。它调度 SwingWorker 以在 worker 线程上执行并立即返回。可以使用 get 方法等待 SwingWorker 完成。
Worker 线程:在此线程上调用 doInBackground() 方法。所有后台活动都应该在此线程上发生。要通知 PropertyChangeListeners 有关绑定 (bound) 属性的更改,请使用 firePropertyChange 和 getPropertyChangeSupport() 方法。默认情况下,有两个可用的绑定属性:state 和 progress。
事件指派线程:所有与 Swing 有关的活动都在此线程上发生。SwingWorker 调用 process 和 done() 方法,并通知此线程的所有 PropertyChangeListener。
通常,当前 线程就是事件指派线程。
在 worker 线程上调用 doInBackground 方法之前,SwingWorker 通知所有 PropertyChangeListener 有关对 StateValue.STARTED 的 state 属性更改。doInBackground 方法完成后,执行 done 方法。然后 SwingWorker 通知所有 PropertyChangeListener 有关对 StateValue.DONE 的 state 属性更改。
SwingWorker 被设计为只执行一次。多次执行 SwingWorker 将不会调用两次 doInBackground 方法。
1 实现SwingWorker的子类 //该类为泛型类,产生类型为T的工作结果和类型为V的进度数据
需要重写的方法
doInBackground(); // 运行在工作线程中,编写执行耗时操作的逻辑代码,并以返回值来作为线程的执行结果。应在此方法中不时地调用publish()方法报告工作进度,几个publish()的调用会引起process()方法的一次调用成批处理
process(); //运行在EDT中,接收一个包含几个中间结果的列表,从列表中提取出数据可直接用于更新UI(通常process仅仅关注每次返回的最后一组值,使用 它来更新GUI):
done(); // 运行在EDT中,任务完成后自动调用,典型地可以使用get()方法得到工作结果数据,对UI进行最后的更新
注意:必须要重写的方法只有doInBackground
2 实例化该子类,调用其execute方法启动该线程
2.4 类SwingWorker类 SwingWorker详解
java.lang.Object
继承者 javax.swing.SwingWorker
类型参数:
T - 此 SwingWorker 的doInBackground 和 get 方法返回的结果类型
V - 用于保存此 SwingWorker 的 publish 和 process 方法的中间结果的类型
所有已实现的接口:
Runnable, Future, RunnableFuture(前两个接口的简单封装)
因为实现了Runnable,所以有run方法,调用FutureTask.run()
因为实现了Future,所以有:
SwingWorker支持bound properties,这个在与其他线程通信时很有作用。提供两个绑定属性:progress 和 state。progress和state可以用于触发在事件派发线程中的事件处理任务。
通过实现一个PropertyChangeListener,程序可以捕捉到progress,state或其他绑定属性的变化。
以下为相关的方法解读:
void addPropertyChangeListener(PropertyChangeListener listener)//通常使用匿名类的做法,任务子类的方法
将PropertyChangeListener添加到侦听器列表。
void firePropertyChange(StringpropertyName,Object oldValue, Object newValue)
向所有已注册的侦听器报告绑定属性更新
int getProgress()
返回progress绑定属性。
PropertyChangeSupport getPropertyChangeSupport()
返回此SwingWorker的PropertyChangeSupport。
protected void setProgress(int progress)
设置progress绑定属性。
典例:使用ProgressBar更新显示进度,很方便地在工作线程与EDT之间进行通信
setProgress(100 * numbers.size() / numbersToFind);
task.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) //需要重写的方法
{
if ("progress".equals(evt.getPropertyName()))//得到属性的名称
{
progressBar.setValue((Integer)evt.getNewValue())//得到属性最新对应的值;
}
}});
更多关于SwingWorker方法的解析:http://www.oschina.net/uploads/doc/javase-6-doc-api-zh_CN/javax/swing/SwingWorker.html