|
JavaTM 2 Platform Standard Ed. 6 |
|||||||||
| 上一個類別 下一個類別 | 框架 無框架 | |||||||||
| 摘要: 巢狀 | 欄位 | 建構子 | 方法 | 詳細資訊: 欄位 | 建構子 | 方法 | |||||||||
java.lang.Objectjavax.swing.SwingWorker<T,V>
T - 此 SwingWorker 的 doInBackground 和 get 方法返回的結果型別V - 用於保存此 SwingWorker 的 publish 和 process 方法的中間結果的型別public abstract class SwingWorker<T,V>
在專用執行緒中執行長時間 GUI 交互任務的抽象類別。
使用 Swing 編寫多執行緒應用程序時,要記住兩個約束條件:(有關詳細資訊,請參閱 How to Use Threads):
這些約束意味著需要時間密集計算操作的 GUI 應用程序至少需要以下兩個執行緒:1) 執行長時間任務的執行緒; 2) 所有 GUI 相關活動的事件指派執行緒 (EDT)這涉及到難以實作的執行緒間通信。
SwingWorker 設計用於需要在後台執行緒中運行長時間運行任務的情況,並可在完成後或者在處理過程中向 UI 提供更新。SwingWorker 的子類別必須實作 doInBackground() 方法,以執行後台計算。
工作串流
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 方法。
範例用法
下例說明了最簡單的使用範例:在後台完成某些處理,並在處理完成後更新 Swing 元件。
假定想找到“Meaning of Life”並在 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 執行。
| 巢狀類別摘要 | |
|---|---|
static class |
SwingWorker.StateValue
state 綁定 (bound) 屬性的值。 |
| 建構子摘要 | |
|---|---|
SwingWorker()
建構此 SwingWorker。 |
|
| 方法摘要 | |
|---|---|
void |
addPropertyChangeListener(PropertyChangeListener listener)
將 PropertyChangeListener 添加到偵聽器列表。 |
boolean |
cancel(boolean mayInterruptIfRunning)
試圖取消對此任務的執行。 |
protected abstract T |
doInBackground()
計算結果;如果無法計算結果,則拋出異常。 |
protected void |
done()
doInBackground 方法完成後,在事件指派執行緒 上執行此方法。 |
void |
execute()
排程此 SwingWorker 以便在 worker 執行緒上執行。 |
void |
firePropertyChange(String propertyName,
Object oldValue,
Object newValue)
向所有已註冊的偵聽器報告綁定屬性更新。 |
T |
get()
如有必要,等待計算完成,然後獲取其結果。 |
T |
get(long timeout,
TimeUnit unit)
如有必要,最多等待為使計算完成所給定的時間之後,獲取其結果(如果結果可用)。 |
int |
getProgress()
返回 progress 綁定屬性。 |
PropertyChangeSupport |
getPropertyChangeSupport()
返回此 SwingWorker 的 PropertyChangeSupport。 |
SwingWorker.StateValue |
getState()
返回 SwingWorker 狀態綁定屬性。 |
boolean |
isCancelled()
如果在任務正常完成前將其取消,則返回 true。 |
boolean |
isDone()
如果任務已完成,則返回 true。 |
protected void |
process(List<V> chunks)
在事件指派執行緒 上非同步地從 publish 方法接收資料塊。 |
protected void |
publish(V... chunks)
將資料塊發送給 process(java.util.List 方法。 |
void |
removePropertyChangeListener(PropertyChangeListener listener)
從偵聽器列表中移除一個 PropertyChangeListener。 |
void |
run()
將此 Future 設置為計算的結果,除非它已經被取消。 |
protected void |
setProgress(int progress)
設置 progress 綁定屬性。 |
| 從類別 java.lang.Object 繼承的方法 |
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| 建構子詳細資訊 |
|---|
public SwingWorker()
SwingWorker。
| 方法詳細資訊 |
|---|
protected abstract T doInBackground()
throws Exception
注意,此方法只執行一次。
註:此方法在後台執行緒中執行。
Exception - 如果無法計算結果public final void run()
Future 設置為計算的結果,除非它已經被取消。
Runnable 中的 runRunnableFuture<T> 中的 runThread.run()protected final void publish(V... chunks)
process(java.util.List) 方法。將從 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;
}
@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) protected void process(List<V> chunks)
publish 方法接收資料塊。
有關詳細資訊,請參閱 publish(V...) 方法。
chunks - 要處理的中間結果publish(V...)protected void done()
doInBackground 方法完成後,在事件指派執行緒 上執行此方法。預設實作不執行任何操作。子類別可以覆寫此方法,以在事件指派執行緒 上執行完成操作。注意,可以查詢此方法實作內部的狀態,以確定此任務的結果或者是否已經取消了此任務。
doInBackground(),
isCancelled(),
get()protected final void setProgress(int progress)
progress 綁定屬性。該值應該在 0 到 100 之間。
由於在事件指派執行緒 上非同步地通知 PropertyChangeListener,所以可以在調用任意 PropertyChangeListener 之前對 setProgress 方法進行多次調用。為了改進性能,所有這些調用都合併為一個只帶最後一個調用參數的調用。
例如,以下調用:
setProgress(1); setProgress(2); setProgress(3);結果可能為帶有值
3 的單個 PropertyChangeListener 通知。
progress - 要設置的進度值
IllegalArgumentException - 如果值不是從 0 到 100public final int getProgress()
progress 綁定屬性。
public final void execute()
SwingWorker 以便在 worker 執行緒上執行。存在許多可用的 worker 執行緒。如果所有 worker 執行緒都忙於處理其他 SwingWorker,則此 SwingWorker 將被放入等待佇列。
註:SwingWorker 被設計為只執行一次。多次執行 SwingWorker 將不會調用兩次 doInBackground 方法。
public final boolean cancel(boolean mayInterruptIfRunning)
此方法返回後,對 Future.isDone() 的後續調用將始終返回 true。如果此方法返回 true,則對 Future.isCancelled() 的後續調用將始終返回 true。
Future<T> 中的 cancelmayInterruptIfRunning - 如果應該中斷執行此任務的執行緒,則為 true;否則允許正在運行的任務運行完成
public final boolean isCancelled()
Future<T> 中的 isCancelledpublic final boolean isDone()
Future<T> 中的 isDone
public final T get()
throws InterruptedException,
ExecutionException
註:在此 SwingWorker 完成之前,在事件指派執行緒 上調用 get 將阻塞所有 事件(包括 repaint)的處理。
想在事件指派執行緒 上阻塞 SwingWorker 時,建議使用 網要對話框(modal dialog)。
例如:
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);
Future<T> 中的 getInterruptedException - 如果當前的執行緒在等待時被中斷
ExecutionException - 如果計算拋出異常
public final T get(long timeout,
TimeUnit unit)
throws InterruptedException,
ExecutionException,
TimeoutException
有關更多資訊,請參閱 get()。
Future<T> 中的 gettimeout - 等待的最大時間unit - timeout 參數的時間單位
InterruptedException - 如果當前的執行緒在等待時被中斷
ExecutionException - 如果計算拋出異常
TimeoutException - 如果等待逾時public final void addPropertyChangeListener(PropertyChangeListener listener)
PropertyChangeListener 添加到偵聽器列表。該偵聽器是為所有屬性註冊的。同一偵聽器對象可以被添加多次,並且它們被調用的次數將與添加它們的次數相同。如果 listener 為 null,則不拋出任何異常並且不執行任何操作。
註:此方法只是一個便捷外覆器。所有工作都委託給 getPropertyChangeSupport() 返回的 PropertyChangeSupport。
listener - 要添加的 PropertyChangeListenerpublic final void removePropertyChangeListener(PropertyChangeListener listener)
PropertyChangeListener。此方法移除一個為所有屬性註冊的 PropertyChangeListener。如果將 listener 多次添加到同一事件源,則在被移除之後,它獲得的通知將減少一次。如果 listener 為 null,或者沒有添加過,則不拋出任何異常並且不執行任何操作。
註:此方法只是一個便捷外覆器。所有工作都委託給 getPropertyChangeSupport() 返回的 PropertyChangeSupport。
listener - 要移除的 PropertyChangeListener
public final void firePropertyChange(String propertyName,
Object oldValue,
Object newValue)
old 和 new 相等並且為非 null,則不觸發任何事件。
此 SwingWorker 將成為所有已產生事件的源。
在事件指派執行緒 之外調用此方法時,則在事件指派執行緒 上非同步地通知 PropertyChangeListener。
註:此方法只是一個便捷外覆器。所有工作都委託給 getPropertyChangeSupport() 返回的 PropertyChangeSupport。
propertyName - 已更改屬性的程式名稱oldValue - 屬性的舊值newValue - 屬性的新值public final PropertyChangeSupport getPropertyChangeSupport()
SwingWorker 的 PropertyChangeSupport。當需要靈活地存取綁定屬性支持時,使用此方法。
此 SwingWorker 將成為所有已產生事件的源。
註:如果在事件指派執行緒 之外調用 firePropertyChange 或 fireIndexedPropertyChange,則返回的 PropertyChangeSupport 在事件指派執行緒 上非同步地通知所有 PropertyChangeListener。
SwingWorker 的 PropertyChangeSupportpublic final SwingWorker.StateValue getState()
SwingWorker 狀態綁定屬性。
|
JavaTM 2 Platform Standard Ed. 6 |
|||||||||
| 上一個類別 下一個類別 | 框架 無框架 | |||||||||
| 摘要: 巢狀 | 欄位 | 建構子 | 方法 | 詳細資訊: 欄位 | 建構子 | 方法 | |||||||||
版權所有 2008 Sun Microsystems, Inc. 保留所有權利。請遵守GNU General Public License, version 2 only。