ゆっちの秘密基地
Master - Yucchi
Since - 2012/05/05


Java秘密基地

SwingWorker を試す その2
JDK1.6 から標準採用となった SwingWorker を試してみます。

前回、試せなかった機能の確認と NetBeans6.0 のプロファイラを使用してみます。

それでは、処理の途中結果を随時取り出すために publish() メソッドと process() メソッドを使ってみましょう。

開発環境は

OS   Windows Vista Ultimate 64bit
JDK6u4
NetBeans IDE 6.0

です。

作成するプログラムはテキストエリアに文字を追加表示させていくというものです。

キャンセルすることも可能とします。

実際のプログラムのスクリーンショットは下図のようになります。




スタートボタンを押すと文字がテキストエリアに表示されていきます。

スタートボタンが無効になります。

キャンセルボタンが有効になります。

プログレスバーの進捗状況が表示されます。





処理が完了すると、スタートボタンが有効になり、キャンセルボタンが無効になります。





処理の途中でキャンセルするとテキストエリアに「キャンセルしました」と追加表示して終了します。





このようなプログラムを作成しました。

実際に動作を確認できるように Java Web Start を配備しました。

Launch ThreadTest 2

JDK1.6 以降のバージョンなら動くと思います。


ソースコードは下記のとおりです。

相変わらず汚いコードですが笑って許してください。(^^;









SwingWorker クラス全体の説明は前回と同じなので省略します。

今回、処理の途中経過を随時取り出すために publish() メソッドと process() メソッド を使用してます。

プログラムの流れとしては publish() メソッド が process() メソッド にデータチャンクを送信します。

そして、process() メソッドがイベントディスパッチスレッド上で、publish() メソッドから非同期でデータチャンクを受信します。


上記プログラムの186行目に publish() メソッドがあります。

そして、publish() メソッドによって送信されたデータチャンクを199行目の process() メソッドで受信します。

これはイベントディスパッチスレッド上で非同期に受信します。

けっこう簡単に作れますね(^^)

ここで隠れた恩恵に注意してみましょう。

SwingWorkerクラスのジェネリクスによる二つの型パラメータです。

今回のように非同期で実行しているスレッドからイベントディスパッチスレッドにデータを引き渡すときに使います。

これを使うことによって以前のバージョンで、このようなアプリケーションを作成する場合にイベントディスパッチスレッドでデータをキャストする必要がありません。

前回のプログラムでは第一型パラメータを使用しましたが今回は第二型パラメータを使ってます。

165行目に記述されているように Integer 型を使用してます。

doInBackground() メソッドで publish() メソッドが呼ばれます。

process() メソッド にデータチャンクを送信します。

process() メソッドの引数は型パラメータのリストとなります。

今回のプログラムでは、List<Integer> となります。

ここで注意が必要なのが publish() メソッドが呼ばれるとすぐに process() メソッドが呼ばれるわけではありません。

process() メソッドはイベントディスパッチスレッドの中でスケジュールされて呼ばれます。

つまり、前回呼ばれてから次に呼ばれるまでの間の publish() メソッドで引き渡されたデータがリストとなって、process() メソッドに渡されます。

このように非同期に行われているスレッドからイベントディスパッチスレッドへデータを簡単に引き渡すことが可能となります。(^^)




さて、前回そして今回と SwingWorker クラス について調べてきました。

ここで下記のようにイベントディスパッチスレッド上に長い処理を記述したプログラムと作るとどうなるか試してみましょう。






スタートボタンを押すと下図のような状態で何も反応しなくなります。


実際に動作を確認できるように Java Web Start を配備しました。

Launch ThreadTest 1

JDK1.6 以降のバージョンなら動くと思います。


       


そして、いきなり完了画面が表示されます。

そこで、NetBeans6.0 に搭載されている高機能なプロファイラを使ってスレッドの状態を確認してみます。

AWT-EventQueue-0 がスタートボタンが押されてから処理が終了するまでの間 Sleeping になってます。

紫色の部分です。

そこをダブルクリックします。






詳細が表示されます。

Details タブを押して詳細画面を切り替えます。






こちらの画面では時間が詳しく確認できます。





このプロファイラを使うことによってイベントディスパッチスレッド上で本来してはいけない長い処理をしているのが確認できます。

よって、スタートボタン・キャンセルボタンの有効、無効の表示の変更が行われない。

もちろんテキストエリアの表示も行われないということですね。

イベントディスパッチスレッドのブロックが解除されてから一気に表示されると不本意な結果となってます。




それでは、SwingWorker クラスを使用し、ちゃんと動作するプログラムをプロファイリングしてみます。

SwingWorker-pool-1-thread-1 が作られてます(^^)

このおかげで、AWT-EventQueue-0 がSleeping にならずにちゃんと動いてます。

よって、GUIの更新がちゃんとされます。















ここで注目なのが SwingWorker は一度だけしか使えないというのが確認できます。

プログラムが終了してから再度スタートボタンを押して再実行させても新たなワーカースレッドが作られます。

下図は4回スタートボタンを押してプログラムを実行したのでワーカースレッドが4つ作成されてます。





この画面でも確認できます。






今回、前回と SwingWorker クラスについて調べました。

とても魅力的なクラスです(^^)

そして、NetBeans6.0 のプロファイラの便利な機能の一部ですが試すこともできました。

このプロファイラを使いたいがために NetBeans を使っているというプログラマもいます。

私には使いこなせない高機能なものですが間違いなく素晴らしいものです!


    Home  Index  Back