- 类型参数:
T- 此SwingWorker'sdoInBackground和get方法返回的结果类型V- 用于通过此SwingWorker'spublish和process方法执行中间结果的类型
- 所有已实现的接口:
Runnable,Future<T>,RunnableFuture<T>
SwingWorker 选择线程的确切策略是未指定的,不应依赖。
使用 Swing 编写多线程应用程序时,需要牢记两个约束条件:(有关更多详细信息,请参阅Swing 中的并发):
- 耗时的任务不应该运行在事件派发线程.否则应用程序将变得无响应。
- 应访问 Swing 组件事件派发线程仅有的。
这些限制意味着具有时间密集型计算的 GUI 应用程序至少需要两个线程:1) 一个线程来执行冗长的任务和 2)事件派发线程(EDT) 用于所有与 GUI 相关的活动。这涉及线程间通信,实现起来可能很棘手。
SwingWorker 专为需要在后台线程中运行长时间运行的任务并在完成或处理时向 UI 提供更新的情况而设计。 SwingWorker 的子类必须实现 doInBackground() 方法来执行后台计算。
工作流程
SwingWorker 的生命周期涉及三个线程:
当前的线程:
execute()方法在该线程上被调用。它安排SwingWorker执行工人线程并立即返回。可以等待SwingWorker使用get方法完成。工人线程:
doInBackground()方法在该线程上被调用。这是所有后台活动应该发生的地方。要通知PropertyChangeListeners有关绑定属性的更改,请使用firePropertyChange和getPropertyChangeSupport()方法。默认情况下,有两个可用的绑定属性:state和progress。事件派发线程:所有与 Swing 相关的活动都发生在该线程上。
SwingWorker调用process和done()方法并通知此线程上的任何PropertyChangeListeners。
通常,当前的线程是事件派发线程.
在调用 doInBackground 方法之前工人线程,SwingWorker 通知任何 PropertyChangeListeners 关于 state 属性更改为 StateValue.STARTED 。 doInBackground 方法完成后,执行 done 方法。然后 SwingWorker 通知任何 PropertyChangeListeners 关于 state 属性更改为 StateValue.DONE 。
SwingWorker 仅设计为执行一次。多次执行 SwingWorker 不会导致调用 doInBackground 方法两次。
示例用法
以下示例说明了最简单的用例。一些处理在后台完成,完成后更新 Swing 组件。
假设我们想要找到“生命的意义”并将结果显示在 JLabel 中。
final JLabel label;
class MeaningOfLifeFinder extends SwingWorker<String, Object> {
@Override
public String doInBackground() {
return findTheMeaningOfLife();
}
@Override
protected void done() {
try {
label.setText(get());
} catch (Exception ignore) {
}
}
}
(new MeaningOfLifeFinder()).execute();
下一个示例在您希望在数据准备就绪时处理数据的情况下很有用事件派发线程.
现在我们要找到前 N 个质数并将结果显示在 JTextArea 中。虽然这是计算,但我们希望在 JProgressBar 中更新我们的进度。最后,我们还想将质数打印到 System.out 。
class PrimeNumbersTask extends
SwingWorker<List<Integer>, Integer> {
PrimeNumbersTask(JTextArea textArea, int numbersToFind) {
//initialize
}
@Override
public List<Integer> doInBackground() {
while (! enough && ! isCancelled()) {
number = nextPrimeNumber();
publish(number);
setProgress(100 * numbers.size() / numbersToFind);
}
}
return numbers;
}
@Override
protected void process(List<Integer> chunks) {
for (int number : chunks) {
textArea.append(number + "\n");
}
}
}
JTextArea textArea = new JTextArea();
final JProgressBar progressBar = new JProgressBar(0, 100);
PrimeNumbersTask task = new PrimeNumbersTask(textArea, N);
task.addPropertyChangeListener(
new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())) {
progressBar.setValue((Integer)evt.getNewValue());
}
}
});
task.execute();
System.out.println(task.get()); //prints all prime numbers we have got
因为 SwingWorker 实现了 Runnable ,所以 SwingWorker 可以提交给 Executor 执行。
- 自从:
- 1.6
-
内部类总结
内部类在接口 java.util.concurrent.Future 中声明的嵌套类/接口
Future.State -
构造方法总结
构造方法 -
方法总结
修饰符和类型方法描述final void将PropertyChangeListener添加到监听器列表。final booleancancel(boolean mayInterruptIfRunning) 尝试取消执行此任务。protected abstract T计算结果,如果无法计算则抛出异常。protected voiddone()执行于事件派发线程doInBackground方法完成后。final voidexecute()安排此SwingWorker执行工人线。final voidfirePropertyChange(String propertyName, Object oldValue, Object newValue) 向任何已注册的监听报告绑定属性更新。final Tget()如有必要,等待计算完成,然后检索其结果。final T如有必要,最多等待计算完成的给定时间,然后检索其结果(如果可用)。final int返回progress绑定属性。final PropertyChangeSupport返回此SwingWorker的PropertyChangeSupport。final SwingWorker.StateValuegetState()返回SwingWorker状态绑定属性。final boolean如果此任务在正常完成之前被取消,则返回true。final booleanisDone()如果此任务完成,则返回true。protected void从publish方法异步接收数据块事件派发线程.protected final void将数据块发送到process(java.util.List<V>)方法。final void从监听器列表中删除PropertyChangeListener。final voidrun()将此Future设置为计算结果,除非它已被取消。protected final voidsetProgress(int progress) 设置progress绑定属性。在类 java.lang.Object 中声明的方法
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait在接口 java.util.concurrent.Future 中声明的方法
exceptionNow, resultNow, state
-
构造方法详细信息
-
SwingWorker
public SwingWorker()构造这个SwingWorker。
-
-
方法详情
-
doInBackground
计算结果,如果无法计算则抛出异常。请注意,此方法仅执行一次。
注意:此方法在后台线程中执行。
- 返回:
- 计算结果
- 抛出:
Exception- 如果无法计算结果
-
run
public final void run()将此Future设置为计算结果,除非它已被取消。- 指定者:
run在接口Runnable中- 指定者:
run在接口RunnableFuture<T>中
-
publish
将数据块发送到process(java.util.List<V>)方法。此方法将从doInBackground方法内部使用,以传递中间结果以在事件派发线程在process方法中。因为
process方法是异步调用的事件派发线程在执行process方法之前,可能会多次调用publish方法。出于性能目的,所有这些调用都合并为一个具有串联参数的调用。例如:
publish("1"); publish("2", "3"); publish("4", "5", "6");可能导致:process("1", "2", "3", "4", "5", "6")示例用法.此代码片段加载一些表格数据并使用它更新
DefaultTableModel。请注意,从process方法内部更改 tableModel 是安全的,因为它是在事件派发线程.class TableSwingWorker extends SwingWorker<DefaultTableModel, Object[]> { private final DefaultTableModel tableModel; public TableSwingWorker(DefaultTableModel tableModel) { this.tableModel = tableModel; }@Overrideprotected DefaultTableModel doInBackground() throws Exception { for (Object[] row = loadData(); ! isCancelled() && row != null; row = loadData()) { publish((Object[]) row); } return tableModel; }@Overrideprotected void process(List<Object[]> chunks) { for (Object[] row : chunks) { tableModel.addRow(row); } } }- 参数:
chunks- 要处理的中间结果- 参见:
-
process
从publish方法异步接收数据块事件派发线程.详情请参考
publish(V...)方法。- 参数:
chunks- 要处理的中间结果- 参见:
-
done
protected void done()执行于事件派发线程doInBackground方法完成后。默认实现什么都不做。子类可以覆盖此方法以对事件派发线程.请注意,您可以在该方法的实现内部查询状态以确定该任务的结果或该任务是否已被取消。- 参见:
-
setProgress
protected final void setProgress(int progress) 设置progress绑定属性。该值应介于 0 到 100 之间。因为
PropertyChangeListener是异步通知的事件派发线程在调用任何PropertyChangeListeners之前,可能会多次调用setProgress方法。出于性能目的,所有这些调用都合并为一个仅包含最后一个调用参数的调用。例如,以下调用:
setProgress(1); setProgress(2); setProgress(3);
可能会产生一个值为3的PropertyChangeListener通知。- 参数:
progress- 要设置的进度值- 抛出:
IllegalArgumentException- 值不在 0 到 100 之间
-
getProgress
public final int getProgress()返回progress绑定属性。- 返回:
- 进度绑定属性。
-
execute
public final void execute()安排此SwingWorker执行工人线。有许多工人线程可用。在所有情况下工人threads are busy handling otherSwingWorkersthisSwingWorkeris placed in a waiting queue.注意:
SwingWorker仅设计为执行一次。多次执行SwingWorker不会导致调用doInBackground方法两次。 -
cancel
public final boolean cancel(boolean mayInterruptIfRunning) 尝试取消执行此任务。如果任务已经完成或取消,或者由于其他原因无法取消,则此方法无效。否则,如果在调用cancel时此任务尚未启动,则此任务永远不会运行。如果任务已经开始,则mayInterruptIfRunning参数确定执行此任务的线程(当实现知道时)是否被中断以试图停止任务。此方法的返回值不一定表示任务现在是否已取消;使用
Future.isCancelled()。 -
isCancelled
public final boolean isCancelled()如果此任务在正常完成之前被取消,则返回true。- 指定者:
isCancelled在接口Future<T>中- 返回:
true如果此任务在完成之前被取消
-
isDone
public final boolean isDone()如果此任务完成,则返回true。完成可能是由于正常终止、异常或取消——在所有这些情况下,此方法将返回true。 -
get
如有必要,等待计算完成,然后检索其结果。注意:调用
get事件派发线程积木all事件,包括重绘,从被处理直到这个SwingWorker完成。当您希望
SwingWorker在事件派发线程我们建议您使用模态对话框.例如:
class SwingWorkerCompletionWaiter implements PropertyChangeListener { private JDialog dialog; public SwingWorkerCompletionWaiter(JDialog dialog) { this.dialog = dialog; } public void propertyChange(PropertyChangeEvent event) { if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.DONE == event.getNewValue()) { dialog.setVisible(false); dialog.dispose(); } } } JDialog dialog = new JDialog(owner, true); swingWorker.addPropertyChangeListener( new SwingWorkerCompletionWaiter(dialog)); swingWorker.execute(); //the dialog will be visible until the SwingWorker is done dialog.setVisible(true);- 指定者:
get在接口Future<T>中- 返回:
- 计算结果
- 抛出:
CancellationException- 如果计算被取消InterruptedException- 如果当前线程在等待时被中断ExecutionException- 如果计算抛出异常
-
get
public final T get(long timeout, TimeUnit unit) throws InterruptedException , ExecutionException , TimeoutException 如有必要,最多等待计算完成的给定时间,然后检索其结果(如果可用)。请参阅
get()了解更多详情。- 指定者:
get在接口Future<T>中- 参数:
timeout- 最长时间等待unit- 超时参数的时间单位- 返回:
- 计算结果
- 抛出:
CancellationException- 如果计算被取消InterruptedException- 如果当前线程在等待时被中断ExecutionException- 如果计算抛出异常TimeoutException- 如果等待超时
-
addPropertyChangeListener
将PropertyChangeListener添加到监听器列表。监听器已为所有属性注册。同一个监听器对象可能被添加多次,添加多少次就会被调用多少次。如果listener是null,则不会抛出异常并且不会采取任何操作。注意:这只是一个方便的包装器。所有工作都从
getPropertyChangeSupport()委托给PropertyChangeSupport。- 参数:
listener- 要添加的PropertyChangeListener
-
removePropertyChangeListener
从监听器列表中删除PropertyChangeListener。这将删除为所有属性注册的PropertyChangeListener。如果listener被多次添加到同一事件源,则在删除后将少通知一次。如果listener是null,或者从未添加过,则不会抛出异常并且不会采取任何操作。注意:这只是一个方便的包装器。所有工作都从
getPropertyChangeSupport()委托给PropertyChangeSupport。- 参数:
listener- 要删除的PropertyChangeListener
-
firePropertyChange
向任何已注册的监听器报告绑定属性更新。如果old和new相等且非空,则不会触发任何事件。这个
SwingWorker将成为任何生成事件的来源。当被叫停事件派发线程
PropertyChangeListeners被异步通知事件派发线程.注意:这只是一个方便的包装器。所有工作都从
getPropertyChangeSupport()委托给PropertyChangeSupport。- 参数:
propertyName- 已更改属性的编程名称oldValue- 属性的旧值newValue- 属性的新值
-
getPropertyChangeSupport
返回此SwingWorker的PropertyChangeSupport。当需要灵活访问绑定属性支持时使用此方法。这个
SwingWorker将成为任何生成事件的来源。注意:返回的
PropertyChangeSupport异步通知任何PropertyChangeListeners事件派发线程如果firePropertyChange或fireIndexedPropertyChange被取消事件派发线程.- 返回:
PropertyChangeSupport对于这个SwingWorker
-
getState
返回SwingWorker状态绑定属性。- 返回:
- 当前状态
-