- java.lang.Object
-
- javax.swing.SwingWorker<T,V>
-
- 参数类型
-
T- 该SwingWorker'sdoInBackground和get方法返回的结果类型 -
V- 用于执行中间结果的类型SwingWorker'spublish和process方法
- All Implemented Interfaces:
-
Runnable,Future<T>,RunnableFuture<T>
public abstract class SwingWorker<T,V> extends Object implements RunnableFuture<T>
在后台线程中执行冗长的GUI交互任务的抽象类。 可以使用几个后台线程来执行这些任务。 然而,为任何特定的SwingWorker选择一个线程的确切策略是未指定的,不应该依赖。当使用Swing编写多线程应用程序时,请注意以下两个限制:(有关详细信息,请参阅Concurrency in Swing ):
- 事件调度线程不应该运行耗时的任务。 否则应用程序将无响应。
- 只能在事件分派线程上访问Swing组件。
这些限制意味着具有时间密集型计算的GUI应用程序至少需要两个线程:1)执行冗长任务的线程; 2)所有GUI相关活动的事件调度线程 (EDT)。 这涉及到可能难以实现的跨线程通信。
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执行SwingWorker不会导致二次调用doInBackground方法。样品用法
以下示例说明了最简单的用例。 一些处理在后台完成,完成后,您可以更新Swing组件。
说我们想找到“生命的意义”,并在
JLabel显示结果。final JLabel label; class MeaningOfLifeFinder extends SwingWorker<String, Object> {@Overridepublic String doInBackground() { return findTheMeaningOfLife(); }@Overrideprotected 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 }@Overridepublic List<Integer> doInBackground() { while (! enough && ! isCancelled()) { number = nextPrimeNumber(); publish(number); setProgress(100 * numbers.size() / numbersToFind); } } return numbers; }@Overrideprotected 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
-
-
Nested Class Summary
Nested Classes Modifier and Type Class 描述 static classSwingWorker.StateValuestate绑定属性的值。
-
构造方法摘要
构造方法 Constructor 描述 SwingWorker()构造这个SwingWorker。
-
方法摘要
所有方法 接口方法 抽象方法 具体的方法 Modifier and Type 方法 描述 voidaddPropertyChangeListener(PropertyChangeListener listener)添加一个PropertyChangeListener到监听器列表。booleancancel(boolean mayInterruptIfRunning)尝试取消执行此任务。protected abstract TdoInBackground()计算一个结果,如果不能这样做,就会抛出一个异常。protected voiddone()doInBackground方法完成后,在 事件发送doInBackground执行。voidexecute()计划这个SwingWorker在 工作线程上执行。voidfirePropertyChange(String propertyName, Object oldValue, Object newValue)向任何已注册的监听器报告绑定属性更新。Tget()等待计算完成,然后检索其结果。Tget(long timeout, TimeUnit unit)如果需要等待最多在给定的时间计算完成,然后检索其结果(如果可用)。intgetProgress()返回progress绑定属性。PropertyChangeSupportgetPropertyChangeSupport()返回这个PropertyChangeSupport的SwingWorker。SwingWorker.StateValuegetState()返回SwingWorker状态绑定属性。booleanisCancelled()如果此任务在正常完成之前被取消,则返回true。booleanisDone()如果此任务完成,则返回true。protected voidprocess(List<V> chunks)在 事件调度线程上异步接收来自publish方法的数据块。protected voidpublish(V... chunks)发送数据块到process(java.util.List<V>)方法。voidremovePropertyChangeListener(PropertyChangeListener listener)从侦听器列表中删除PropertyChangeListener。voidrun()将此Future设置为计算结果,除非已被取消。protected voidsetProgress(int progress)设置progress绑定属性。
-
-
-
方法详细信息
-
doInBackground
protected abstract T doInBackground() throws 异常
计算一个结果,如果不能这样做,就会抛出一个异常。请注意,此方法只执行一次。
注意:该方法在后台线程中执行。
- 结果
- 计算结果
- 异常
-
异常- 如果无法计算结果
-
run
public final void run()
将此Future设置为计算结果,除非已被取消。- Specified by:
-
run在接口Runnable - Specified by:
-
run在接口RunnableFuture<T> - 另请参见:
-
Thread.run()
-
publish
@SafeVarargs protected final void publish(V... chunks)
发送数据块到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方法中process。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(java.util.List<V>)
-
process
protected void process(List<V> chunks)
在事件调度线程上异步接收来自publish方法的数据块。详情请参考
publish(V...)方法。- 参数
-
chunks- 要处理的中间结果 - 另请参见:
-
publish(V...)
-
done
protected void done()
完成doInBackground方法后,在事件发送doInBackground执行。 默认实现什么都不做。 子类可以覆盖此方法以在事件分派线程上执行完成操作。 请注意,您可以在该方法的实现中查询状态,以确定此任务的结果或此任务是否已被取消。- 另请参见:
-
doInBackground(),isCancelled(),get()
-
setProgress
protected final void setProgress(int progress)
设置progress绑定属性。 该值应该在0到100之间。因为
PropertyChangeListener在事件调度线程上被异步通知,因此在调用任何PropertyChangeListeners之前,可能会发生多项到setProgress方法的调用。 为了执行目的,所有这些调用都合并到一个调用中,最后一个调用参数。例如,以下调用:
setProgress(1); setProgress(2); setProgress(3);可能会导致一个PropertyChangeListener通知,值为3。- 参数
-
progress- 要设置的进度值 - 异常
-
IllegalArgumentException- 值不是从0到100
-
getProgress
public final int getProgress()
返回progress绑定属性。- 结果
- 进度绑定属性。
-
execute
public final void execute()
计划这个SwingWorker用于在工作线程上执行。 有多个工作线程可用。 在所有工作线程正忙于处理其他SwingWorkers情况下,SwingWorker被放置在等待队列中。注意:
SwingWorker仅被设计为执行一次。SwingWorker执行SwingWorker不会导致二次调用doInBackground方法。
-
cancel
public final boolean cancel(boolean mayInterruptIfRunning)
尝试取消执行此任务。 如果任务已经完成,已经被取消或由于某种其他原因而无法取消,则此尝试将失败。 如果成功,并且当cancel时此任务尚未启动,则此任务不应运行。 如果任务已经开始,那么mayInterruptIfRunning参数确定执行此任务的线程是否应该中断,以试图停止任务。此方法返回后,后续调用
Future.isDone()将始终返回true。 对后续调用Future.isCancelled()总是返回true如果此方法返回true。
-
isCancelled
public final boolean isCancelled()
如果此任务在正常完成之前被取消,则返回true。- Specified by:
-
isCancelled在接口Future<T> - 结果
-
true如果此任务在完成之前被取消
-
isDone
public final boolean isDone()
如果此任务完成,则返回true。 完成可能是由于正常终止,异常或取消 - 在所有这些情况下,此方法将返回true。
-
get
public final T get() throws InterruptedException, ExecutionException
等待计算完成,然后检索其结果。注意:在事件分派线程上调用
get阻止所有事件(包括重绘)被处理,直到完成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);- Specified by:
-
get在接口Future<T> - 结果
- 计算结果
- 异常
-
InterruptedException- 如果当前线程在等待时中断 -
ExecutionException- 如果计算抛出异常
-
get
public final T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
如果需要等待最多在给定的时间计算完成,然后检索其结果(如果可用)。详情请参阅
get()。- Specified by:
-
get在接口Future<T> - 参数
-
timeout- 等待的最长时间 -
unit- 超时参数的时间单位 - 结果
- 计算结果
- 异常
-
InterruptedException- 如果当前线程在等待时中断 -
ExecutionException- 如果计算抛出异常 -
TimeoutException- 如果等待超时
-
addPropertyChangeListener
public final void addPropertyChangeListener(PropertyChangeListener listener)
添加一个PropertyChangeListener到监听器列表。 所有属性都注册了监听器。 同一个侦听器对象可以被多次添加,并且将被调用多次,因为它被添加。 如果listener为null,则不会抛出异常并且不采取任何操作。注意:这只是一个方便的包装。 所有工作
PropertyChangeSupportgetPropertyChangeSupport()委派至PropertyChangeSupport 。- 参数
-
listener- 要添加的PropertyChangeListener
-
removePropertyChangeListener
public final void removePropertyChangeListener(PropertyChangeListener listener)
从侦听器列表中删除PropertyChangeListener。 这将删除所有属性注册的PropertyChangeListener。 如果listener添加到同一个事件源,则被删除后将被通知一次。 如果listener是null,或者从未添加过,则不会抛出异常并且不采取任何操作。注意:这只是一个方便的包装。 所有的工作都委托给
PropertyChangeSupport从getPropertyChangeSupport()。- 参数
-
listener- 要删除的PropertyChangeListener
-
firePropertyChange
public final void firePropertyChange(String propertyName, Object oldValue, Object newValue)
向任何已注册的监听器报告绑定属性更新。 如果old和new相等且非空,则old触发任何事件。这个
SwingWorker将是任何生成的事件的源。当调用事件调度线程
PropertyChangeListeners被异步通知事件分派线程时 。注意:这只是一个方便的包装。 所有的工作都委托给
PropertyChangeSupport从getPropertyChangeSupport()。- 参数
-
propertyName- 已更改的属性的编程名称 -
oldValue- 该物业的旧值 -
newValue- 该物业的新值
-
getPropertyChangeSupport
public final PropertyChangeSupport getPropertyChangeSupport()
返回PropertyChangeSupport为这个SwingWorker。 当需要灵活访问绑定属性支持时,使用此方法。这个
SwingWorker将是任何生成的事件的源。注:返回
PropertyChangeSupport通知任何PropertyChangeListener小号异步对事件的事件调度线程firePropertyChange或者fireIndexedPropertyChange被叫停事件指派线程 。- 结果
-
PropertyChangeSupport为这SwingWorker
-
getState
public final SwingWorker.StateValue getState()
返回SwingWorker状态绑定属性。- 结果
- 当前状态
-
-