- 型パラメータ:
T
- このSwingWorker's
のdoInBackground
メソッドおよびget
メソッドによって返される結果の型V
- このSwingWorker's
のpublish
メソッドおよびprocess
メソッドを使って中間結果を計算するために使用する型
- すべての実装されたインタフェース:
Runnable
,Future<T>
,RunnableFuture<T>
public abstract class SwingWorker<T,V> extends Object implements RunnableFuture<T>
SwingWorker
のスレッドを選択する厳密な方法は指定されていないため、それに依存してはいけません。
Swingを使用してマルチスレッド・アプリケーションを記述する場合は、次の2つの制約に注意してください(詳細は「Concurrency in Swing」を参照)。
- イベント・ディスパッチ・スレッドでは時間のかかるタスクを実行しないようにしてください。 アプリケーションが応答しなくなります。
- Swingコンポーネントには、イベント・ディスパッチ・スレッド上でのみアクセスするようにしてください。
これらの制約があるため、時間のかかるGUIアプリケーションには、1)時間のかかるタスクを実行するスレッドと、2) GUI関連のすべての作業を実行するイベント・ディスパッチ・スレッド (EDT)の少なくとも2つのスレッドが必要になります。 このように複数のスレッドを使用する場合はスレッド間通信を行う必要がありますが、この機能は簡単に実装できない場合があります。
SwingWorker
は、バックグラウンド・スレッドで実行時間の長いタスクを実行する必要があり、その実行中または実行完了後にUIを更新する必要がある場合を想定して設計されています。 SwingWorker
のサブクラスは、バックグラウンドで計算を行うため、doInBackground()
メソッドを実装する必要があります。
ワークフロー
SwingWorker
のライフ・サイクル内には、次の3つのスレッドが存在します。
-
現在のスレッド:
execute()
メソッドはこのスレッド上で呼び出されます。 このメソッドは、ワーカー・スレッドでのSwingWorker
の実行スケジュールを立て、その情報をただちに返します。get
メソッドを使ってSwingWorker
の完了を待機することもできます。 -
ワーカー・スレッド:
doInBackground()
メソッドはこのスレッド上で呼び出されます。 ここで、すべてのバックグラウンド作業が発生します。PropertyChangeListeners
にバウンド・プロパティの変更を通知するには、firePropertyChange
メソッドとgetPropertyChangeSupport()
メソッドを使用します。 デフォルトでは、state
とprogress
の2つのバウンド・プロパティを使用できます。 -
イベント・ディスパッチ・スレッド: Swing関連のすべての作業は、このスレッド上で発生します。
SwingWorker
はprocess
メソッドとdone()
メソッドを呼び出し、このスレッド上のすべてのPropertyChangeListeners
に通知します。
現在のスレッドがイベント・ディスパッチ・スレッドである場合もあります。
ワーカー・スレッド上で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
SwingWorker
はRunnable
を実装するので、SwingWorker
をExecutor
に送信して実行できます。
- 導入されたバージョン:
- 1.6
-
ネストされたクラスのサマリー
ネストされたクラス 修飾子と型 クラス 説明 static class
SwingWorker.StateValue
state
バウンド・プロパティの値です。 -
コンストラクタのサマリー
コンストラクタ コンストラクタ 説明 SwingWorker()
このSwingWorker
を構築します。 -
メソッドのサマリー
修飾子と型 メソッド 説明 void
addPropertyChangeListener(PropertyChangeListener listener)
リスナー・リストにPropertyChangeListener
を追加します。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()
このSwingWorker
のPropertyChangeSupport
を返します。SwingWorker.StateValue
getState()
SwingWorker
状態バウンド・プロパティを返します。protected void
process(List<V> chunks)
イベント・ディスパッチ・スレッドで、publish
メソッドから非同期でデータ・チャンクを受信します。protected void
publish(V... chunks)
process(java.util.List<V>)
メソッドにデータ・チャンクを送信します。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
インタフェース java.util.concurrent.Futureで宣言されたメソッド
cancel, isCancelled, isDone
-
コンストラクタの詳細
-
SwingWorker
public SwingWorker()このSwingWorker
を構築します。
-
-
メソッドの詳細
-
doInBackground
結果を計算するか、計算できない場合は例外をスローします。このメソッドは1回だけ実行されます。
ノート: このメソッドは、バックグラウンド・スレッドで実行されます。
- 戻り値:
- 計算結果
- 例外:
Exception
- 結果を計算できなかった場合
-
run
public final void run()取り消されていなければ、このFuture
に計算結果を設定します。- 定義:
run
、インタフェース:Runnable
- 定義:
run
、インタフェース:RunnableFuture<T>
- 関連項目:
Thread.run()
-
publish
@SafeVarargsprotected final void publish(V... chunks)process(java.util.List<V>)
メソッドにデータ・チャンクを送信します。 このメソッドは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<V>)
-
process
イベント・ディスパッチ・スレッドで、publish
メソッドから非同期でデータ・チャンクを受信します。詳細については、
publish(V...)
メソッドを参照してください。- パラメータ:
chunks
- 処理対象となる中間結果- 関連項目:
publish(V...)
-
done
protected void done()doInBackground
メソッドの実行完了後、イベント・ディスパッチ・スレッドで実行されます。 デフォルト実装は何も実行しません。 サブクラスは、このメソッドをオーバーライドして、イベント・ディスパッチ・スレッド上で完了処理を実行することがあります。 このメソッドの実装内部でステータスを照会して、このタスクの結果や、このタスクが取り消されていないかどうかを確認できます。 -
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回しか呼び出されません。 -
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);
- 定義:
get
、インタフェース:Future<T>
- 戻り値:
- 計算結果
- 例外:
CancellationException
- 計算が取り消された場合InterruptedException
- 待機中に現在のスレッドで割込みが発生した場合ExecutionException
- 計算で例外がスローされた場合
-
get
public final T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException必要に応じて、最大で指定された時間、計算が完了するまで待機し、その後、計算結果が利用可能な場合は結果を取得します。詳細については、
get()
を参照してください。- 定義:
get
、インタフェース:Future<T>
- パラメータ:
timeout
- 待機する最長時間unit
- timeout引数の時間単位- 戻り値:
- 計算結果
- 例外:
CancellationException
- 計算が取り消された場合InterruptedException
- 待機中に現在のスレッドで割込みが発生した場合ExecutionException
- 計算で例外がスローされた場合TimeoutException
- 待機がタイム・アウトになった場合
-
addPropertyChangeListener
public final void addPropertyChangeListener(PropertyChangeListener listener)リスナー・リストにPropertyChangeListener
を追加します。 リスナーは、すべてのプロパティに対して登録されます。 同じリスナー・オブジェクトを複数回追加でき、追加した回数だけリスナー・オブジェクトが呼び出されます。listener
がnull
の場合、例外はスローされず、何も処理は行われません。ノート: これは簡易ラッパーです。 すべての処理は、
getPropertyChangeSupport()
からPropertyChangeSupport
に委譲されます。- パラメータ:
listener
- 追加されるPropertyChangeListener
-
removePropertyChangeListener
public final void removePropertyChangeListener(PropertyChangeListener listener)PropertyChangeListener
をリスナー・リストから削除します。 すべてのプロパティに登録されたPropertyChangeListener
を削除します。 同じイベント・ソースにlistener
が2回以上追加された場合は、削除されたあとに1回少ない通知が行われます。listener
がnull
の場合、または追加されなかった場合、例外はスローされず、何も処理は行われません。ノート: これは簡易ラッパーです。 すべての処理は、
getPropertyChangeSupport()
からPropertyChangeSupport
に委譲されます。- パラメータ:
listener
- 削除するPropertyChangeListener
-
firePropertyChange
すべての登録済みリスナーにバウンド・プロパティが更新されたことを報告します。old
値とnew
値が等しく、nullでない場合、イベントはトリガーされません。この
SwingWorker
は、生成されるすべてのイベントのソースになります。イベント・ディスパッチ・スレッドを取り消した場合、
PropertyChangeListeners
はイベント・ディスパッチ上で非同期で通知を受信します。ノート: これは簡易ラッパーです。 すべての処理は、
getPropertyChangeSupport()
からPropertyChangeSupport
に委譲されます。- パラメータ:
propertyName
- 変更されたプロパティのプログラム名oldValue
- プロパティの古い値newValue
- プロパティの新しい値
-
getPropertyChangeSupport
public final PropertyChangeSupport getPropertyChangeSupport()このSwingWorker
のPropertyChangeSupport
を返します。 このメソッドは、バウンド・プロパティに頻繁にアクセスする必要がある場合に使用します。この
SwingWorker
は、生成されるすべてのイベントのソースになります。ノート:
firePropertyChange
またはfireIndexedPropertyChange
がイベント・ディスパッチ・スレッドを取り消した場合、返されるPropertyChangeSupport
は、イベント・ディスパッチ・スレッド上のすべてのPropertyChangeListener
に非同期で通知を送信します。- 戻り値:
- この
SwingWorker
のPropertyChangeSupport
-
getState
public final SwingWorker.StateValue getState()SwingWorker
状態バウンド・プロパティを返します。- 戻り値:
- 現在の状態
-