T - 此
SwingWorker's
doInBackground和
get方法返回的结果类型
V - 用于执行中间结果的类型
SwingWorker's
publish和
process方法
public abstract class SwingWorker<T,V> extends Object implements RunnableFuture<T>
SwingWorker选择一个线程的确切策略是未指定的,不应该依赖。
当使用Swing编写多线程应用程序时,请注意以下两个限制:(有关详细信息,请参阅Concurrency in Swing ):
这些限制意味着具有时间密集型计算的GUI应用程序至少需要两个线程:1)执行冗长任务的线程; 2)所有GUI相关活动的事件调度线程 (EDT)。 这涉及到可能难以实现的跨线程通信。
SwingWorker适用于需要在后台线程中运行长时间运行的任务并在完成或处理时向UI提供更新的情况。 SwingWorker的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执行。
| Modifier and Type | Class and Description |
|---|---|
static class |
SwingWorker.StateValue
值为
state绑定属性。
|
| Constructor and Description |
|---|
SwingWorker()
构造这个
SwingWorker 。
|
| Modifier and Type | Method and Description |
|---|---|
void |
addPropertyChangeListener(PropertyChangeListener listener)
添加一个
PropertyChangeListener到侦听器列表。
|
boolean |
cancel(boolean mayInterruptIfRunning)
尝试取消执行此任务。
|
protected abstract T |
doInBackground()
计算一个结果,如果不能这样做,就会抛出一个异常。
|
protected void |
done()
在
doInBackground方法完成后,在
事件调度线程上执行。
|
void |
execute()
调度此
SwingWorker以在
工作线程上执行。
|
void |
firePropertyChange(String propertyName, Object oldValue, Object newValue)
向任何已注册的监听器报告绑定属性更新。
|
T |
get()
等待计算完成,然后检索其结果。
|
T |
get(long timeout, TimeUnit unit)
如果需要等待最多在给定的时间计算完成,然后检索其结果(如果可用)。
|
int |
getProgress()
返回
progress绑定属性。
|
PropertyChangeSupport |
getPropertyChangeSupport()
返回
PropertyChangeSupport此
SwingWorker 。
|
SwingWorker.StateValue |
getState()
返回
SwingWorker状态绑定属性。
|
boolean |
isCancelled()
如果此任务在正常完成之前被取消,则返回
true 。
|
boolean |
isDone()
返回
true如果任务已完成。
|
protected void |
process(List<V> chunks)
在
事件调度线程上
publish从
publish方法接收数据块。
|
protected void |
publish(V... chunks)
发送数据块到
process(java.util.List<V>)方法。
|
void |
removePropertyChangeListener(PropertyChangeListener listener)
从侦听器列表中删除一个
PropertyChangeListener 。
|
void |
run()
将此
Future设置为计算结果,除非已被取消。
|
protected void |
setProgress(int progress)
设置
progress绑定属性。
|
protected abstract T doInBackground() throws 异常
请注意,此方法只执行一次。
注意:该方法在后台线程中执行。
异常 - 如果无法计算结果
public final void run()
Future设置为计算结果,除非已被取消。
run在接口
Runnable
run在接口
RunnableFuture<T>
Thread.run()
@SafeVarargs protected final void publish(V... chunks)
process(java.util.List<V>)方法。
此方法是从里面使用doInBackground方法在里面的事件指派线程提供用于处理中间结果process方法。
因为process方法是异步调用的事件指派线程多次调用到publish方法之前,可能会出现process执行方法。 为了表现目的,所有这些调用都合并成一个带有连接参数的调用。
例如:
publish("1");
publish("2", "3");
publish("4", "5", "6");
可能会导致:
process("1", "2", "3", "4", "5", "6")
样品用法 。 此代码段加载了一些表格数据和更新DefaultTableModel 。 请注意,在process方法中,因为在事件分派线程中调用process ,因此它是安全的。
class TableSwingWorker extends
SwingWorker<DefaultTableModel, Object[]> {
private final DefaultTableModel tableModel;
public TableSwingWorker(DefaultTableModel tableModel) {
this.tableModel = tableModel;
}
@Override
protected DefaultTableModel doInBackground() throws Exception {
for (Object[] row = loadData();
! isCancelled() && row != null;
row = loadData()) {
publish((Object[]) row);
}
return tableModel;
}
@Override
protected void process(List<Object[]> chunks) {
for (Object[] row : chunks) {
tableModel.addRow(row);
}
}
}
chunks - 要处理的中间结果
process(java.util.List<V>)
protected void process(List<V> chunks)
publish从publish方法接收数据块。
有关详细信息,请参阅publish(V...)方法。
chunks - 要处理的中间结果
publish(V...)
protected void done()
doInBackground方法完成后在事件调度线程上执行。
默认实现什么都不做。
子类可以覆盖此方法以在事件分派线程上执行完成操作。
请注意,您可以在该方法的实现中查询状态,以确定此任务的结果或此任务是否已被取消。
doInBackground() ,
isCancelled() ,
get()
protected final void setProgress(int progress)
progress绑定属性。
该值应该在0到100之间。
因为PropertyChangeListener在事件调度线程上PropertyChangeListener通知,在调用任何PropertyChangeListeners之前,可能会发生对setProgress方法的PropertyChangeListeners调用。 为了执行目的,所有这些调用都合并到一个调用中,最后一个调用参数。
例如,以下调用:
setProgress(1);
setProgress(2);
setProgress(3);
可能会导致一个单独的PropertyChangeListener通知,值为3 。
progress - 要设置的进度值
IllegalArgumentException - 值不是从0到100
public final int getProgress()
progress绑定属性。
public final void execute()
SwingWorker以在工作线程上执行。
有多个工作线程可用。
在所有工作线程正忙于处理其他SwingWorkers这SwingWorker被放置在等待队列中。
注意: SwingWorker仅被设计为执行一次。 多次执行SwingWorker不会导致调用doInBackground方法两次。
public final boolean cancel(boolean mayInterruptIfRunning)
cancel被调用时,这个任务应该运行。
如果任务已经开始,那么mayInterruptIfRunning参数确定是否执行此任务的线程应该以试图停止任务被中断。
此方法返回后,后续调用Future.isDone()将始终返回true 。 随后电话Future.isCancelled()总是返回true如果此方法返回true 。
public final boolean isCancelled()
true 。
isCancelled在接口
Future<T>
true如果此任务在完成之前被取消
public final boolean isDone()
true如果任务已完成。
完成可能是由于正常终止,异常或取消 - 在所有这些情况下,此方法将返回true 。
public final T get() throws InterruptedException, ExecutionException
注意:在事件调度线程上调用get阻止所有事件(包括重绘)被处理直到此SwingWorker完成。
当您想要SwingWorker阻止事件调度线程时,我们建议您使用模态对话框 。
例如:
class SwingWorkerCompletionWaiter extends 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>
InterruptedException - 如果当前线程在等待时中断
ExecutionException - 如果计算抛出异常
public final T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
详情请参考get() 。
get在接口
Future<T>
timeout - 等待的最长时间
unit - 超时参数的时间单位
InterruptedException - 如果当前线程在等待时中断
ExecutionException - 如果计算引发异常
TimeoutException - 如果等待超时
public final void addPropertyChangeListener(PropertyChangeListener listener)
PropertyChangeListener到监听器列表。
所有属性都注册了监听器。
同一个侦听器对象可以被多次添加,并且将被调用多次,因为它被添加。
如果listener是null ,那么抛出异常并且不采取任何操作。
注意:这只是一个方便的包装。 所有工作由getPropertyChangeSupport() PropertyChangeSupport至PropertyChangeSupport 。
listener - 要加入的
PropertyChangeListener
public final void removePropertyChangeListener(PropertyChangeListener listener)
PropertyChangeListener 。
这消除了一个PropertyChangeListener已注册的所有属性。
如果listener添加到同一个事件源, listener删除后将被通知一次。
如果listener是null ,或者从未添加过,则不会抛出任何异常,也不会采取任何操作。
注意:这只是一个方便的包装。 所有工作由getPropertyChangeSupport() PropertyChangeSupport给PropertyChangeSupport 。
listener - 要删除的
PropertyChangeListener
public final void firePropertyChange(String propertyName, Object oldValue, Object newValue)
old和new相等且非空,则old触发任何事件。
这SwingWorker将是任何生成的事件的源。
如果取消了事件指派线程 PropertyChangeListeners是在事件指派线程上异步地通知。
注意:这只是一个方便的包装。 所有工作均由PropertyChangeSupport至PropertyChangeSupport 。
propertyName - 已更改的属性的编程名称
oldValue - 该属性的旧值
newValue - 该物业的新值
public final PropertyChangeSupport getPropertyChangeSupport()
PropertyChangeSupport为这SwingWorker 。
当需要灵活访问绑定属性支持时,使用此方法。
此SwingWorker将是任何生成的事件的源。
注:返回PropertyChangeSupport通知任何PropertyChangeListener小号异步对事件的事件调度线程 firePropertyChange或fireIndexedPropertyChange被叫停事件指派线程 。
PropertyChangeSupport为这
SwingWorker
public final SwingWorker.StateValue getState()
SwingWorker状态绑定属性。
Submit a bug or feature
For further API reference and developer documentation, see Java SE Documentation. That documentation contains more detailed, developer-targeted descriptions, with conceptual overviews, definitions of terms, workarounds, and working code examples.
Copyright © 1993, 2014, Oracle and/or its affiliates. All rights reserved.