職場で後輩に教えたことの備忘録だけど、後々役立つかもしれないからこっちにも保存。
権利云々は…大丈夫だと思うけど、この程度なら。書いたのあたしだし、文面考えたのもあたしだし。特定業務のネタも…入ってないな、よし。
なお…。あたし個人の方針として定義したパターンなので、明らかな間違い以外は突っ込み無用デス。
1. 基礎知識
1.1 Swingについて
- Swingに関わる処理はスレッドセーフではない。
- Swingは、Swingに関わる処理を行うためのスレッドを1本だけ持っている。
- Swingスレッド以外のスレッドからSwingに関わる処理を実行するためには、Swingスレッドに処理内容を伝達する必要がある。
- Swingスレッド以外のスレッドからは、Swingスレッド内でどの処理を実行しているか(ある処理が終わったか否か)を知ることはできない。
- Swingスレッドは1本しかないので、スレッド内で長時間処理を行うと、その間GUIは更新されずにフリーズし、白抜き画面などになってしまう。
1.2 スレッド、Runnableについて
- Runnableは「run()メソッドを持つ」ことを定義するインタフェース。
- スレッドはRunnableインタフェース実装クラスの1種。
「run()メソッドに書かれた処理を、他のスレッドとは独立した時間軸で実行する」
- スレッドの開始は、start()メソッドで行う。start()の実行によってスレッドはJava VMに対し、実行権を要求する。
直接run()を実行しても、スレッドにはならない。
- Java VMが実行権を与えたタイミングで、スレッドのrun()が実際に実行される。
2. Swing GUI処理の実装基本パターン
2.1 お約束
- Swingに関わらない処理は、基本的にSwingから独立したスレッドとして実装する。
2.2 基本パターン
- -- Swingイベントスレッド内 --
- Swingイベントの発生(ボタンのActionPerformed()呼び出しなど)。
- 処理に必要なデータをGUIから取得(選択されているデータ、入力文字列等)。
- 処理スレッドのインスタンス生成、必要データのセット。
- GUIのロック(全ボタンを使用不能にする、等)。
- 処理スレッドの開始、Swingイベントの終了。
- -- 以下、処理スレッド内 --
- 処理の実行(DBアクセス、計算等)。
- GUI更新Runnableのインスタンス生成、GUI更新データのセット。
- GUI更新RunnableインスタンスをSwingUtilities.invokeLater()を使用してSwingイベント待ち行列に追加。
- ループ処理の場合、8)~10)を繰り返す。
- (全処理終了後)GUIのロック解除Runnableのインスタンス生成、
SwingUtilities.invokeLater()を使用してSwingイベント待ち行列に追加。
- 処理スレッドの終了。
- -- 以下、再びSwingイベントスレッド --
- 10)で追加されたRunnableを順番に実行。
- 12)で追加されたRunnableを実行、GUIロック解除。
- 全終了。