|
JavaTM 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 とやりとりする時間のかかるタスクを、専用のスレッドで実行するための abstract クラスです。
Swing を使ってマルチスレッドアプリケーションを記述する場合は、次の 2 つの制約に注意してください (詳細は「How to Use Threads」を参照)。
これらの制約があるため、時間のかかる 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 に送信して、実行することができます。
| 入れ子のクラスの概要 | |
|---|---|
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()
この 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
このメソッドは 1 回だけ実行されます。
注:このメソッドは、バックグラウンドスレッドで実行されます。
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 メソッドが複数回呼び出されることがあります。パフォーマンスの向上のため、これらのすべての呼び出しは 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) 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 メソッドはイベントディスパッチスレッド上で非同期で通知を受け取るので、PropertyChangeListeners が呼び出される前に、setProgress メソッドが複数回呼び出されることがあります。パフォーマンスの向上のため、これらのすべての呼び出しは 1 回の呼び出しにまとめられます。この場合、最後の呼び出しの引数だけが有効になります。
たとえば、次の呼び出しがあるとします。
setProgress(1); setProgress(2); setProgress(3);これは、値
3 を持つ 1 回の PropertyChangeListener 通知にまとめられます。
progress - 設定する進捗値
IllegalArgumentException - 0 〜 100 以外の値を指定した場合public final int getProgress()
progress バウンドプロパティーを返します。
public final void execute()
SwingWorker の実行スケジュールを立てます。多数のワークスレッドを使用できます。すべてのワークスレッドがほかの SwingWorkers の処理でビジー状態になっている場合、この SwingWorker は待機キューに入ります。
注:SwingWorker は 1 回だけ実行されるように設計されています。SwingWorker を複数回実行しても、doInBackground メソッドは 1 回しか呼び出されません。
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
注:イベントディスパッチスレッド上で 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> 内の 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 Platform Standard Ed. 6 |
|||||||||
| 前のクラス 次のクラス | フレームあり フレームなし | |||||||||
| 概要: 入れ子 | フィールド | コンストラクタ | メソッド | 詳細: フィールド | コンストラクタ | メソッド | |||||||||
Copyright 2009 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. Documentation Redistribution Policy も参照してください。