SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

作って覚えるJavaプログラミングのススメ

Java入門 (9) - タイマーとスレッド

作って覚えるJavaプログラミングのススメ 第9回

SwingUtilitiesの利用

 ここまで述べたスレッドの利用方法は、GUIを使わない場合は問題ありません。しかし、Swingのコンポーネントなどを利用する場合には、ちょっとした注意が必要です。

 実は、Swingのコンポーネントは複数のスレッドから同時にアクセスすることを考えて作られていません。先ほどの様に、別スレッドからコンポーネントを操作する手法は望ましくないのです。

 Swingコンポーネントをメインスレッド以外から操作する場合には、Swing関係のユーティリティ機能をまとめたSwingUtilitiesクラスから、invokeLaterメソッドを使って操作することが推奨されています。例えばrunメソッドをこんな具合にしてやるのです。

invokeLaterによる実装
public void run() {
    while(roop_flag){
        try {
            Thread.sleep(1000);
        } catch(InterruptedException e){
            e.printStackTrace();
        }
        SwingUtilities.invokeLater(new Runnable(){
            public void run(){
                setTime();
            }
        });
    }
}

 runメソッドの中から、さらにRunnablerunメソッドを実行してるのでちょっと分かりにくいのですが、SwingUtilities.invokeLaterというメソッドを呼び出し、この引数内にRunnableを無名クラスとして組み込んでいることが分かるでしょう。そして、そのrunメソッドでsetTimeを呼び出しています。

 このSwingUtilities.invokeLaterは、イベント処理関係のスレッドが一通り終了したところでこのスレッドを安全に実行してくれるメソッドです。Swingのコンポーネントの表示を更新するような処理は、このようにして安全にスレッドを実行するようにしておきます。

 注意しておきたいのは、このループを使ってエンドレスで実行するrun自体をSwingUtilities.invokeLaterからまるごと実行してはまずい、という点です。このinvokeLaterは、Swingのイベント関係の処理を行うスレッド(イベントディスパッチスレッドと呼ばれる特別なスレッドです)に、必要なrunの処理をはめ込んで実行します。

 このため、サンプルの時計のように、エンドレスで実行され続ける処理をここに入れてしまうと、その処理でこのスレッドが占有され、GUIの操作ができなくなってしまいます。

 あくまで、コンポーネントを更新する必要最低限の操作部分だけをinvokeLaterで実行させるようにしてください。

 実はこのSwingUtilities.invokeLaterは、Swingを利用する上で非常に重要なものなのです。今まで、Swingのコンポーネントを動かす際は、当たり前のように以下の要領でJFrameを実行していました。

今までのJFrameの実行方法
public static void main(String args[]) {
    Sample sample1 = new Sample();
    sample1.setBounds(100,100,300,200);
    sample1.setVisible(true);
}

 これも、Swingのコンポーネントを操作するスレッドは安全に実行できるように注意するという観点からすれば、実はあまりいいやり方ではないのです。本来であれば以下のようにすべきです。

Swingのコンポーネントを操作するスレッドの書き方
public static void main(String args[]) {
    SwingUtilities.invokeLater(new Runnable(){
        public void run(){
            Sample sample1 = new Sample();
            sample1.setBounds(100,100,300,200);
            sample1.setVisible(true);
        }
    });
}

 Swingコンポーネントを別スレッドで実行する際の基本として、SwingUtilities.invokeLaterを使ってスレッドを実行するというやり方は覚えておくとよいでしょう。

次のページ
スレッドの開始と終了

この記事は参考になりましたか?

作って覚えるJavaプログラミングのススメ連載記事一覧

もっと読む

この記事の著者

掌田 津耶乃(ショウダ ツヤノ)

三文ライター&三流プログラマ。主にビギナーに向けたプログラミング関連の執筆を中心に活動している。※現在、入門ドキュメントサイト「libro」、カード型学習サイト「CARD.tuyano.com」を公開...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/2597 2008/06/24 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー