←前頁 | 次頁→ |
---|
その7(アプレット3)
今度の例題は、スレッドの扱いかたです。
説明がかなり長くなりましたが、がんばって読んで下さい。
スレッドの停止のさせかたが面倒なのでよく見ておいて下さい。
ついでに、アプレットへのパラメータの渡しかたも見ておいてね。
今回は、RdxApplet2クラスをさらに拡張(extends)して作成します。
本アプレットは、一定時間毎にロゴの色を変えます。
/** RDXアプレットプログラム 指定時間(msec)毎に色を変えます HTML例↓ <applet code="RdxApplet3.class" codebase="." width="320" height="120"> <parameter name=interval value="5000"> </applet> @author 服部建作 @version 1.0 1999/10/18 */ //アプレットを定義する為のパッケージ(必須) import java.applet.*; //描画関係のパッケージ import java.awt.*; //イベント関係のパッケージ import java.awt.event.*; public class RdxApplet3 extends RdxApplet2 implements Runnable{ //変数宣言 static int interval = 5000; //default 5秒間隔 volatile Thread changeThread; //スレッドオブジェクト //動作間隔のパラメータを取得する為にオーバーライド public void init(){ super.init(); String param = getParameter("interval"); if( param != null){ interval = Integer.parseInt(param); } } //描画更新処理(ちらつきが気になる時は以下のコメントをとる) //public void update(Graphics g){ // paint(g); //} //Appletの表示が開始された時ブラウザ-から呼ばれる public void start(){ //スレッドの生成 changeThread = new Thread(this); changeThread.start(); } //Appletが表示されなくなった時ブラウザ-から呼ばれる public void stop(){ //割込みを通知する為にオブジェクト参照を作成 Thread tempThread = changeThread; //スレッド停止を伝えるためnullをセット changeThread = null; //即時停止するよう割り込みをかける tempThread.interrupt(); } //スレッドの実処理 public void run(){ Thread thisThread = Thread.currentThread(); while( changeThread == thisThread){ try{ thisThread.sleep(interval); }catch( Exception e){ System.out.println( e); continue; } ChangeColor(); } } }コンパイルの仕方
- 今回は、RdxApplet2クラスを参照しているので、コンパイル時にRdxApplet2.javaファイルを RdxApplet3.javaファイルと同一ディレクトリに置いてコンパイルします。
- RdxApplet2はRdxAppletを参照しているので、RdxApplet.javaも同一ディレクトリに置きます。
- javac RdxApplet3.java とやると、RdxApplet2.javaあるいはRdxApplet.javaもコンパイル してくれます。
- RdxApplet2.classとRdxApplet.classファイルがあればRdxApplet2.javaやRdxApplet.java がなくてもコンパイルできます。
- 実行時は、RdxApplet.class RdxApplet2.classと RdxApplet3.classが同じディレクトリにないといけません。
パラメータについて
- アプレットのパラメータは、コメントにあるように、HTMLファイルの<applet>タグ内 の<param>タグで指定します。
- <param>タグの name="..." でパラメータ名を、value="..."で値を指定します。
- 値は文字列(String)のみ指定できるので、プログラム中では、整数に変換しています。
- プログラム中でパラメータを取得するには、getParameter(パラメータ名)という Appletクラスのメソッドを使用します。
- パラメータは実行時に変化しないので、init()メソッドで行うのがよいでしょう。
- 今回は RdxApplet2クラスを拡張しているので、RdxApplet2クラスのinit()を実行してから パラメータの処理を追加しています。
(親クラスのメソッドを実行する場合は、super.メソッド()でしたね。)スレッドについて
- スレッドというのは、一つのプログラム内でマルチタスク(並)の処理を行うものです。
- JAVAでスレッドを生成するには、Threadクラスのオブジェクトを生成します。
- Threadを作成するクラスはRunnableインターフェースをインプリメントしなければなりません。
( "implements Runnable" をつける。)- Runnableインターフェースの代わりにThreadクラスをextendsする方法もあります。
- いずれにしても、該当クラスに run()メソッドを定義しなければ行けません。
- Threadコンストラクタの引数には、上記のRunnableインターフェースを備えた クラスのオブジェクト(変数)を指定します。
- パラメータは実行時に変化しないので、init()メソッドで行うのがよいでしょう。
- 今回は RdxAppletクラスを拡張しているので、RdxAppletクラスのinit()を実行してから パラメータの処理を追加しています。
(親クラスのメソッドを実行する場合は、super.メソッド()でしたね。)- スレッドは、start()メソッドで開始させます。
- スレッドは開始すると、コンストラクタで指定されたRunnableなオブジェクトの run()メソッドを実行します。
- 通常このrun()メソッドを永久ループにしてスレッドの処理を記述します。
- 当然ですが、run()メソッド中では適宜sleep()などしてCPUを開放しないと マルチスレッド・プロセスのメリットがなくなってしまいます。
- スレッドの停止のさせかたは,難しいです。古くはstop()メソッドとかを使っていました が新しいバージョンでは使用してはいかん(というコンパイラの警告が表示されます。)
- でもって例題にあるように、停止させるフラグ変数(changeThread)を決めて、スレッドの中でチェック しています。
- でもってsleep()中だと困るので、interrupt()を発行してsleep()を中断させています。
(この時 Exceptionエラーが発生してsleep()メソッドが中断します。)- やはりスレッドの説明は難しいので、各自 オンラインマニュアルのThreadクラスを参照するように。
volatileについて
- volatileは変数への修飾子の1つです。
- ロジック上は変わりませんが、コンパイラがこの変数への参照をバイナリ コードに落とす時の最適化を抑止します。
- 最適化を抑止して何の得がとお思いでしょうが、最適化されるとループ内で 参照している場合にループが開始時に変数の値を一度参照し、以後ループ中では 最初に参照した値だけを使って処理をするというコードにされてしまうかもしれません。
- この場合のように参照している変数が他のスレッドや処理で変更される可能性の ある時は、自分のプロセスで変更していないからと言って最初に参照した値で ループを回っていると永久に終りません。
- 今回の場合のように変数に毎回地道にアクセスしてほしい場合にvolatile修飾子をつけます。
ちらつき防止について
- コメントにあるように Appletクラスのupdate()メソッドをオーバーライドすると ちらつきを防止することができます。
- デフォルトのupdate()メソッドは領域をクリアしてからpaint()を呼ぶという仕組み になっている(らしい)ので今回の場合だとインターバル時間を短くすると結構ちらつき ます。
エラー処理について
- 以前にtry-catchのエラー処理を手軽に行うには、e.getMessage()でメッセージを 取出して表示すればよいと言いましたが、
- System.out.println( e);とすると、エラーメッセージとともにエラーの クラスを表示します。
(今回の場合は、java.lang.InterruptedException: operation interrupted と表示されます。)
スレッド(thread):
←前頁 次頁→ JAVA オンラインマニュアル:
- マルチプロセスやフォークと同じ。(と言ってしまえば言い過ぎ?)
- プロセスと違ってメモリー空間を共有するので、スレッド間では情報交換が 割と楽にできる(はず)
- 逆に言えば、スレッドは独立性が弱いので下手をすると親のプロセスごと心中する (かもしれない)
- θred [名]糸、ねじれ[動]糸を通す。
なんで発音しにくい単語をコンピュータ用語にするかな。
- 日本語公式マニュアルは、 http://java.sun.com/products/jdk/1.2/docs/ja/を参照するように。
- APIリファレンスを直接参照するときは、 http://java.sun.com/products/jdk/1.2/docs/ja/api
- このマニュアルは圧縮された状態で20Mほどもあるが、ジャワ言人をめざす人は がんぱってダウンロードしよう。