|
JavaTM 2 Platform Standard Ed. 6 |
|||||||||
上一個類別 下一個類別 | 框架 無框架 | |||||||||
摘要: 巢狀 | 欄位 | 建構子 | 方法 | 詳細資訊: 欄位 | 建構子 | 方法 |
java.lang.Object javax.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
中的 run
RunnableFuture<T>
中的 run
Thread.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>
中的 cancel
mayInterruptIfRunning
- 如果應該中斷執行此任務的執行緒,則為 true;否則允許正在運行的任務運行完成
public final boolean isCancelled()
Future<T>
中的 isCancelled
public 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>
中的 get
InterruptedException
- 如果當前的執行緒在等待時被中斷
ExecutionException
- 如果計算拋出異常public final T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
有關更多資訊,請參閱 get()
。
Future<T>
中的 get
timeout
- 等待的最大時間unit
- timeout 參數的時間單位
InterruptedException
- 如果當前的執行緒在等待時被中斷
ExecutionException
- 如果計算拋出異常
TimeoutException
- 如果等待逾時public final void addPropertyChangeListener(PropertyChangeListener listener)
PropertyChangeListener
添加到偵聽器列表。該偵聽器是為所有屬性註冊的。同一偵聽器對象可以被添加多次,並且它們被調用的次數將與添加它們的次數相同。如果 listener
為 null
,則不拋出任何異常並且不執行任何操作。
註:此方法只是一個便捷外覆器。所有工作都委託給 getPropertyChangeSupport()
返回的 PropertyChangeSupport
。
listener
- 要添加的 PropertyChangeListener
public 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
的 PropertyChangeSupport
public final SwingWorker.StateValue getState()
SwingWorker
狀態綁定屬性。
|
JavaTM 2 Platform Standard Ed. 6 |
|||||||||
上一個類別 下一個類別 | 框架 無框架 | |||||||||
摘要: 巢狀 | 欄位 | 建構子 | 方法 | 詳細資訊: 欄位 | 建構子 | 方法 |
版權所有 2008 Sun Microsystems, Inc. 保留所有權利。請遵守GNU General Public License, version 2 only。