JavaTM 2 Platform
Standard Ed. 6

javax.swing
類別 SwingWorker<T,V>

java.lang.Object
  繼承者 javax.swing.SwingWorker<T,V>
型別參數:
T - 此 SwingWorkerdoInBackgroundget 方法返回的結果型別
V - 用於保存此 SwingWorkerpublishprocess 方法的中間結果的型別
所有已實作的介面:
Runnable, Future<T>, RunnableFuture<T>

public abstract class SwingWorker<T,V>
extends Object
implements RunnableFuture<T>

在專用執行緒中執行長時間 GUI 交互任務的抽象類別。

使用 Swing 編寫多執行緒應用程序時,要記住兩個約束條件:(有關詳細資訊,請參閱 How to Use Threads):

這些約束意味著需要時間密集計算操作的 GUI 應用程序至少需要以下兩個執行緒:1) 執行長時間任務的執行緒; 2) 所有 GUI 相關活動的事件指派執行緒 (EDT)這涉及到難以實作的執行緒間通信。

SwingWorker 設計用於需要在後台執行緒中運行長時間運行任務的情況,並可在完成後或者在處理過程中向 UI 提供更新。SwingWorker 的子類別必須實作 doInBackground() 方法,以執行後台計算。

工作串流

SwingWorker 的生命週期中包含三個執行緒:

通常,當前 執行緒就是事件指派執行緒

worker 執行緒上調用 doInBackground 方法之前,SwingWorker 通知所有 PropertyChangeListener 有關對 StateValue.STARTEDstate 屬性更改。doInBackground 方法完成後,執行 done 方法。然後 SwingWorker 通知所有 PropertyChangeListener 有關對 StateValue.DONEstate 屬性更改。

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 執行。

從以下版本開始:
1.6

巢狀類別摘要
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()
          返回此 SwingWorkerPropertyChangeSupport
 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
 

建構子詳細資訊

SwingWorker

public SwingWorker()
建構此 SwingWorker

方法詳細資訊

doInBackground

protected abstract T doInBackground()
                             throws Exception
計算結果;如果無法計算結果,則拋出異常。

注意,此方法只執行一次。

註:此方法在後台執行緒中執行。

返回:
計算的結果
拋出:
Exception - 如果無法計算結果

run

public final void run()
將此 Future 設置為計算的結果,除非它已經被取消。

指定者:
介面 Runnable 中的 run
指定者:
介面 RunnableFuture<T> 中的 run
另請參見:
Thread.run()

publish

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)

process

protected void process(List<V> chunks)
事件指派執行緒 上非同步地從 publish 方法接收資料塊。

有關詳細資訊,請參閱 publish(V...) 方法。

參數:
chunks - 要處理的中間結果
另請參見:
publish(V...)

done

protected void done()
doInBackground 方法完成後,在事件指派執行緒 上執行此方法。預設實作不執行任何操作。子類別可以覆寫此方法,以在事件指派執行緒 上執行完成操作。注意,可以查詢此方法實作內部的狀態,以確定此任務的結果或者是否已經取消了此任務。

另請參見:
doInBackground(), isCancelled(), get()

setProgress

protected final void setProgress(int progress)
設置 progress 綁定屬性。該值應該在 0 到 100 之間。

由於在事件指派執行緒 上非同步地通知 PropertyChangeListener,所以可以在調用任意 PropertyChangeListener 之前對 setProgress 方法進行多次調用。為了改進性能,所有這些調用都合併為一個只帶最後一個調用參數的調用。

例如,以下調用:

setProgress(1);
setProgress(2);
setProgress(3);
 
結果可能為帶有值 3 的單個 PropertyChangeListener 通知。

參數:
progress - 要設置的進度值
拋出:
IllegalArgumentException - 如果值不是從 0 到 100

getProgress

public final int getProgress()
返回 progress 綁定屬性。

返回:
progress 綁定屬性。

execute

public final void execute()
排程此 SwingWorker 以便在 worker 執行緒上執行。存在許多可用的 worker 執行緒。如果所有 worker 執行緒都忙於處理其他 SwingWorker,則此 SwingWorker 將被放入等待佇列。

註:SwingWorker 被設計為只執行一次。多次執行 SwingWorker 將不會調用兩次 doInBackground 方法。


cancel

public final boolean cancel(boolean mayInterruptIfRunning)
試圖取消對此任務的執行。如果任務已完成、或已取消,或者由於某些其他原因而無法取消,則此嘗試將失敗。當調用 cancel 時,如果調用成功,而此任務尚未啟動,則此任務將永不運行。如果任務已經啟動,則 mayInterruptIfRunning 參數確定是否應該以試圖停止任務的方式來中斷執行此任務的執行緒。

此方法返回後,對 Future.isDone() 的後續調用將始終返回 true。如果此方法返回 true,則對 Future.isCancelled() 的後續調用將始終返回 true

指定者:
介面 Future<T> 中的 cancel
參數:
mayInterruptIfRunning - 如果應該中斷執行此任務的執行緒,則為 true;否則允許正在運行的任務運行完成
返回:
如果無法取消任務,則返回 false,這通常是由於它已經正常完成;否則返回 true

isCancelled

public final boolean isCancelled()
如果在任務正常完成前將其取消,則返回 true

指定者:
介面 Future<T> 中的 isCancelled
返回:
如果任務完成前將其取消,則返回 true

isDone

public final boolean isDone()
如果任務已完成,則返回 true。 可能由於正常終止、異常或取消而完成,在所有這些情況中,此方法都將返回 true

指定者:
介面 Future<T> 中的 isDone
返回:
如果任務已完成,則返回 true

get

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 - 如果計算拋出異常

get

public final T get(long timeout,
                   TimeUnit unit)
            throws InterruptedException,
                   ExecutionException,
                   TimeoutException
如有必要,最多等待為使計算完成所給定的時間之後,獲取其結果(如果結果可用)。

有關更多資訊,請參閱 get()

指定者:
介面 Future<T> 中的 get
參數:
timeout - 等待的最大時間
unit - timeout 參數的時間單位
返回:
計算的結果
拋出:
InterruptedException - 如果當前的執行緒在等待時被中斷
ExecutionException - 如果計算拋出異常
TimeoutException - 如果等待逾時

addPropertyChangeListener

public final void addPropertyChangeListener(PropertyChangeListener listener)
PropertyChangeListener 添加到偵聽器列表。該偵聽器是為所有屬性註冊的。同一偵聽器對象可以被添加多次,並且它們被調用的次數將與添加它們的次數相同。如果 listenernull,則不拋出任何異常並且不執行任何操作。

註:此方法只是一個便捷外覆器。所有工作都委託給 getPropertyChangeSupport() 返回的 PropertyChangeSupport

參數:
listener - 要添加的 PropertyChangeListener

removePropertyChangeListener

public final void removePropertyChangeListener(PropertyChangeListener listener)
從偵聽器列表中移除一個 PropertyChangeListener。此方法移除一個為所有屬性註冊的 PropertyChangeListener。如果將 listener 多次添加到同一事件源,則在被移除之後,它獲得的通知將減少一次。如果 listenernull,或者沒有添加過,則不拋出任何異常並且不執行任何操作。

註:此方法只是一個便捷外覆器。所有工作都委託給 getPropertyChangeSupport() 返回的 PropertyChangeSupport

參數:
listener - 要移除的 PropertyChangeListener

firePropertyChange

public final void firePropertyChange(String propertyName,
                                     Object oldValue,
                                     Object newValue)
向所有已註冊的偵聽器報告綁定屬性更新。如果 oldnew 相等並且為非 null,則不觸發任何事件。

SwingWorker 將成為所有已產生事件的源。

事件指派執行緒 之外調用此方法時,則在事件指派執行緒 上非同步地通知 PropertyChangeListener

註:此方法只是一個便捷外覆器。所有工作都委託給 getPropertyChangeSupport() 返回的 PropertyChangeSupport

參數:
propertyName - 已更改屬性的程式名稱
oldValue - 屬性的舊值
newValue - 屬性的新值

getPropertyChangeSupport

public final PropertyChangeSupport getPropertyChangeSupport()
返回此 SwingWorkerPropertyChangeSupport。當需要靈活地存取綁定屬性支持時,使用此方法。

SwingWorker 將成為所有已產生事件的源。

註:如果在事件指派執行緒 之外調用 firePropertyChangefireIndexedPropertyChange,則返回的 PropertyChangeSupport事件指派執行緒 上非同步地通知所有 PropertyChangeListener

返回:
SwingWorkerPropertyChangeSupport

getState

public final SwingWorker.StateValue getState()
返回 SwingWorker 狀態綁定屬性。

返回:
當前狀態

JavaTM 2 Platform
Standard Ed. 6

提交錯誤或意見

版權所有 2008 Sun Microsystems, Inc. 保留所有權利。請遵守GNU General Public License, version 2 only