JavaTM Platform
Standard Ed. 6

javax.swing
クラス SwingWorker<T,V>

java.lang.Object
  上位を拡張 javax.swing.SwingWorker<T,V>
型パラメータ:
T - この SwingWorkerdoInBackground メソッドおよび get メソッドによって返される結果の型
V - この SwingWorkerpublish メソッド および process メソッドを使って中間結果を計算するために使用する型
すべての実装されたインタフェース:
Runnable, Future<T>, RunnableFuture<T>

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

GUI とやりとりする時間のかかるタスクを、専用のスレッドで実行するための abstract クラスです。

Swing を使ってマルチスレッドアプリケーションを記述する場合は、次の 2 つの制約に注意してください (詳細は「How to Use Threads」を参照)。

これらの制約があるため、時間のかかる GUI アプリケーションには、1) 時間のかかるタスクを実行するスレッドと、2) GUI 関連のすべての作業を実行するイベントディスパッチスレッド (EDT) の少なくとも 2 つのスレッドが必要になります。このように複数のスレッドを使用する場合はスレッド間通信を行う必要がありますが、この機能は簡単に実装できない場合があります。

SwingWorker は、バックグラウンドスレッドで実行時間の長いタスクを実行する必要があり、その実行中または実行完了後に UI を更新する必要がある場合を想定して設計されています。SwingWorker のサブクラスは、バックグラウンドで計算を行うため、doInBackground() メソッドを実装する必要があります。

ワークフロー

SwingWorker のライフサイクル内には、次の 3 つのスレッドが存在します。

現在のスレッドがイベントディスパッチスレッドである場合もあります。

ワークスレッド上で doInBackground メソッドが呼び出される前に、SwingWorker はすべての PropertyChangeListeners に、state プロパティーの値が StateValue.STARTED に変更されたことを通知します。doInBackground メソッドの実行が完了すると、done メソッドが実行されます。続いて、SwingWorker はすべての PropertyChangeListeners に、state プロパティーの値が StateValue.DONE に変更されたことを通知します。

SwingWorker は 1 回だけ実行されるように設計されています。SwingWorker を複数回実行しても、doInBackground メソッドは 1 回しか呼び出されません。

使用例

次に、もっとも単純な使用例を示します。一部の処理はバックグラウンドで実行されます。実行が完了したら、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
 

SwingWorkerRunnable を実装するので、SwingWorkerExecutor に送信して、実行することができます。

導入されたバージョン:
1.6

入れ子のクラスの概要
static class SwingWorker.StateValue
          state バウンドプロパティーの値です。
 
コンストラクタの概要
SwingWorker()
          この SwingWorker を構築します。
 
メソッドの概要
 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()
          この 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
結果を計算するか、計算できない場合は例外をスローします。

このメソッドは 1 回だけ実行されます。

注:このメソッドは、バックグラウンドスレッドで実行されます。

戻り値:
計算結果
例外:
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 メソッドが複数回呼び出されることがあります。パフォーマンスの向上のため、これらのすべての呼び出しは 1 回の呼び出しにまとめられます。各呼び出しの引数は連結されます。

例を示します。  

 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 メソッドはイベントディスパッチスレッド上で非同期で通知を受け取るので、PropertyChangeListeners が呼び出される前に、setProgress メソッドが複数回呼び出されることがあります。パフォーマンスの向上のため、これらのすべての呼び出しは 1 回の呼び出しにまとめられます。この場合、最後の呼び出しの引数だけが有効になります。

たとえば、次の呼び出しがあるとします。  

 setProgress(1);
 setProgress(2);
 setProgress(3);
 
これは、値 3 を持つ 1 回の PropertyChangeListener 通知にまとめられます。

パラメータ:
progress - 設定する進捗値
例外:
IllegalArgumentException - 0 〜 100 以外の値を指定した場合

getProgress

public final int getProgress()
progress バウンドプロパティーを返します。

戻り値:
progress バウンドプロパティー

execute

public final void execute()
このメソッドは、ワークスレッドでの SwingWorker の実行スケジュールを立てます。多数のワークスレッドを使用できます。すべてのワークスレッドがほかの SwingWorkers の処理でビジー状態になっている場合、この SwingWorker は待機キューに入ります。

注:SwingWorker は 1 回だけ実行されるように設計されています。SwingWorker を複数回実行しても、doInBackground メソッドは 1 回しか呼び出されません。


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
必要に応じて計算が完了するまで待機し、その後、計算結果を取得します。

注:イベントディスパッチスレッド上で 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); 
 

定義:
インタフェース 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)
すべての登録済みリスナーにバウンドプロパティーが更新されたことを報告します。old 値と new 値が等しく、null でない場合、イベントはトリガーされません。

この SwingWorker は、生成されるすべてのイベントのソースになります。

イベントディスパッチスレッドを取り消した場合、PropertyChangeListener はイベントディスパッチ上で非同期で通知を受信します。

注:これは簡易ラッパーです。すべての処理は、getPropertyChangeSupport() から PropertyChangeSupport に委譲されます。

パラメータ:
propertyName - 変更されたプロパティーのプログラム名
oldValue - プロパティーの変更前の値
newValue - プロパティーの変更後の値

getPropertyChangeSupport

public final PropertyChangeSupport getPropertyChangeSupport()
この SwingWorkerPropertyChangeSupport を返します。このメソッドは、バウンドプロパティーに頻繁にアクセスする必要がある場合に使用します。

この SwingWorker は、生成されるすべてのイベントのソースになります。

注:firePropertyChange または fireIndexedPropertyChange がイベントディスパッチスレッドを取り消した場合、返される PropertyChangeSupport は、イベントディスパッチスレッド上のすべての PropertyChangeListener に非同期で通知を送信します。

戻り値:
この SwingWorkerPropertyChangeSupport

getState

public final SwingWorker.StateValue getState()
SwingWorker 状態バウンドプロパティーを返します。

戻り値:
現在の状態

JavaTM Platform
Standard Ed. 6

バグの報告と機能のリクエスト
さらに詳しい API リファレンスおよび開発者ドキュメントについては、Java SE 開発者用ドキュメントを参照してください。開発者向けの詳細な解説、概念の概要、用語の定義、バグの回避策、およびコード実例が含まれています。

Copyright 2009 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. Documentation Redistribution Policy も参照してください。