[???] / [Java FAQ] / [S019]
S019: スレッド - thread(生成/起動/停止)

[S019 Q-01]
Back
スレッド(thread) ってなんですか? [S019 A-01] スレッド(thread)とは、プログラム内で複数の処理を並行に実行したい ときに使用するものです。 Javaでは、スレッドと対応する java.lang.Thread クラスを用意していま す。新しいスレッドを動かすには、java.lang.Thread クラスのインスタ ンスを作り、その start メソッドを呼ぶことが基本となります。start メソッドについては、S019-05 を参照してください。 また、並列で行わせたい処理は run メソッドに記述します。run メソッ ドについては、S019-04 を参照して下さい。 並列に実行する処理の実装方法としては、java.lang.Thread クラスのサ ブクラスを用意する方法と、java.lang.Runnable インタフェースを実装 したクラスを用意する方法との2つの方法があります。どちらの方法を とるのが良いかについては、S019-16 を参考にして下さい。 java.lang.Runnable については、S019-02 を参照してください。 以下に、java.lang.Thread クラスのサブクラスを用意する方法による 簡単な例を示します。 // ThreadTest.java public class ThreadTest { class Counter extends java.lang.Thread { public void run() { for (int i=0 ; i<10 ; i++) { System.out.println("Counter: " + i); try { sleep(1000); } catch(java.lang.InterruptedException e) { } } } } Counter counter; public ThreadTest() { counter = new Counter(); counter.start(); } public static void main(String[] args) { ThreadTest test = new ThreadTest(); } } P1 に、1秒ごとに iの値をプリントするスレッドと、2秒ごとに iの 値をプリントするスレッドを用意し、並列に動作させるプログラムの 例を示しました。興味のある方は御覧下さい。
[S019 Q-02]
Back
Runnable ってなんですか? [S019-A-02] java.lang.Runnable インタフェースのことです。 Java で提供されているスレッド(thread) の実装方法の1つです。スレッ ドについては、S019-01 を参照して下さい。 java.lang.Runnable インタフェースでは、引数のないメソッド run だけ が宣言されています。java.lang.Runnable インタフェースを実装するク ラスは、この run メソッドに並列で行わせたい処理を記述して下さい。 run メソッドについては、S019-04 を参照して下さい。 並列に実行する処理の実装方法としては、java.lang.Thread クラスのサ ブクラスを用意する方法と、java.lang.Runnable インタフェースを実装 したクラスを用意する方法との2つの方法があります。 前者の実装方法については、S019-01 を参照して下さい。 どちらの方法をとるかについては、S019-16 を参考にして下さい。 以下に、java.lang.Runnable インタフェースを実装したクラスを用意す る方法による簡単な例を示します。 P2 に、実行方法も含めて例を示しました。興味のある方はそちらを御 覧下さい。 ポイントは、次の行です。 runner = new java.lang.Thread(this); runner.start(); java.lang.Thread のインスタンス runner 生成時に、java.lang.Runnable インタフェースを実装したクラスのインスタンス this を引数に指定して いることです。これにより、runner は、this.run() メソッドを呼び出す ことができるようになるのです。java.lang.Thread のインスタンス runner 生成後、並列処理とするために、runner の start メソッドを呼び 出しています。 1秒ごとに i の値を Java コンソールに出力するアプレットの例です。 簡単にアニメーションアプレットなどへ応用できるでしょう。 // ThreadTestApplet.java public class ThreadTestApplet extends java.applet.Applet implements java.lang.Runnable { volatile java.lang.Thread runner; public void init() { runner = null; } public void start() { if (runner == null) { runner = new java.lang.Thread(this); runner.start(); } } public void run( ) { java.lang.Thread thisThread = java.lang.Thread.currentThread(); while (runner == thisThread) { for (int i=0 ; i<5 ; i++) { System.out.println("Count: " + i); try { thisThread.sleep(1000); } catch(java.lang.InterruptedException e) { } } } } public void stop() { runner = null; } }
[S019 Q-03]
Back
デッドロック(deadlock) ってなんですか? [S019 A-03] 複数のスレッド(thread)がお互いに必要なリソースの一部を取り合う などして、それ以上先に進めなくなってしまった状態をデッドロック (deadlock)といいます。 デッドロックの回避についての詳細は、[S021 :同期と排他制御]が参考 になるでしょう。 参考記事 [JavaHouse-Brewers:7220]
[S019 Q-04]
Back
なぜスレッドの run メソッドを呼び出さなくてもスレッドの run メソッドの処理が動くのですか? [S019 A-04] java.lang.Thread クラスのインスタンスは、start メソッドが呼ばれる と、次にrun メソッドを呼ぶようになっているからです。 参考にしているプログラムを見てみると、どこかで java.lang.Thread クラスの start メソッドを呼んでいるはずです。 [参考] run メソッドは、本質的に、新しく作成されたスレッドにとっての main メソッドと考えることもできます。 java.lang.Thread クラスのサブクラスを使って並列処理を実現する場合 は、並列に行いたい処理をサブクラスの run メソッドに記述し、親クラ スの何もしない run メソッドをオーバーライドします。 java.lang.Thread クラスのインスタンスが、別個の Runnable 実行オブジ ェクトを使用して生成された場合、その Runnable オブジェクトのrun メソッドが呼び出されます。これにより、Java VMは、Runnable インタ フェースを実装したクラスの run メソッドを並列に処理することができ ます。 run メソッドに記述された処理が終了すると、スレッド(thread)は終了 します。逆に言うと、run メソッドに無限ループを記述すると、スレッ ドは特別な処理をしない限り終了しません。気を付けて下さい。 スレッドの終了の仕方については、S019-10 を参考にして下さい。 * 注意 run メソッドは、スレッドから何度も呼ばれて実行されると勘違いす る人もいるようですが、start メソッドから 1度しか呼ばれませんので、 注意して下さい。 java.lang.Thread クラスのインスタンス生成のときに、ターゲットとし て Runnable を実装したクラス R を引数に渡した場合、新規スレッドは run メソッドの中で R.run() メソッドを呼びます。java.lang.Thread の サブクラスの場合は、ターゲットを自分自身として run メソッドを呼び ます。 ターゲットの run メソッドが終了すると、スレッドの実行も停止します。 再度実行したい場合は、新しく java.lang.Thread クラスのインスタンス を生成し、start() する必要が有ります。S019-05 も参照して下さい。 参考記事 [JavaHouse-Brewers:1567],[JavaHouse-Brewers:824]
[S019 Q-05]
Back
一度処理が終了したスレッドの使い回しはできますか? [S019 A-05] できません。 スレッドは 1度しか起動することができません。スレッドが停止してい ない状態で start メソッドを呼び出すと、 java.lang.IllegalThreadStateException が発生します。 1度停止した スレッドの start メソッドを呼んだ場合は何も起きません。 サンプルプログラムは P5 を参照してください。 参考記事 [JavaHouse-Brewers:8774]
[S019 Q-06]
Back
安易にsuspend()するとデッドロックになることがあるというのは本当ですか? [S019 A-06] 本当です。 次の簡単な例は、タイムスライシングによるスケジューリングポリシ を採用している Java VM (Win32版など)ではデッドロック(deadlock) が起きる可能性があります。 Solaris などの、ラウンドロビンによるスケジューリングポリシを採用 しているシステムの場合には、問題なく動作します。 この例では、 1. TestThread のインスタンスが System.out をロック。 2. SuspendTest.main() 内の t.suspend() によって TestThread のイ ンスタンスはサスペンド。 3. SuspendTest.main() 内の System.out.println() は System.out が ロックされているので、処理ができずにブロックされる。した がって、SuspendTest は停止。 4. TestThread のインスタンスはレジュームされないので停止した まま、System.out をロック。 5. System.out をめぐり、TestThread と SuspendTest の間でデッド ロックが発生してプログラムは停止。 となります。 // SuspendTest.java import java.lang.Thread; public class SuspendTest { public static void main(String[] args) { TestThread t = new TestThread(); t.start(); Thread.yield(); t.suspend(); System.out.println("suspend TestThread"); // <= blocked t.resume(); System.out.println("main end"); } } // TestThread.java import java.lang.Thread; public class TestThread extends Thread { public void run() { for(int i = 0; i <= 1000; i++) { System.out.println("i = " + i); // <=System.out lock } } } Thread.stop(), Thread.suspend(), Thread.resume(), は Java2 以降 では、deprecate されています。したがって、Java2 SDK 以降でコン パイルをすると、Warning が出力されます。 参考記事 [JavaHouse-Brewers:7220]
[S019 Q-07]
Back
Thread.stop() メソッドが JDK1.2 で deprecated になったのはなぜですか? [S019 A-07] Thread.stop() メソッド が本質的に安全ではないからです。 任意の場所でスレッド(thread)を強制的に停止すると、モニタの状態に 不整合を残したままにしてしまう危険性があります。この結果、壊れた オブジェクトが残り、そのオブジェクトに対しスレッドを操作すると、 予期しない動作を引き起こす可能性があります。 参考記事 [JavaHouse-Brewers:19131]
[S019 Q-08]
Back
Thread.suspend() メソッドが JDK1.2 で deprecated になったのはなぜですか? [S019 A-08] Thread.suspend()メソッド が本質的に安全ではないからです。 参考記事 [JavaHouse-Brewers:7220]
[S019 Q-09]
Back
スレッドが動作しているかどうか調べるにはどうすれば良いのですか? [S019 A-09] Thread.isAlive() メソッドを使用します。 Thread.isAlive() メソッドは、スレッド(thread)が生きているとみなせ る場合は true, みなせない場合は false を返すメソッドです。スレッド が生きているというのは「スレッドが起動(start)されていて、まだ終 了(stop)されていない場合」です。 start していない状態で stop されたスレッドは、start した直後に停 止するように待機している状態になります。この場合は、isAlive() メ ソッドは false を返しますが、ガーベッジコレクタの対象にはならない ので、注意が必要です。start をした後に stop をしたのかどうかを判定 したい場合には、フラグを用意するなどの対処が必要です。 複数のスレッドを連携させて動作させる場合に、他のスレッドが処理を 終了した後に処理を続行したい場合には、isAlive() メソッドを使って 判定をするのではなく、join() メソッドの方を使用することを検討して みてください。 参考記事 [JavaHouse-Brewers:9379],[JavaHouse-Brewers:13895]
[S019 Q-10]
Back
スレッド(thread)を止めるには、どうするのですか? [S019 A-10] run() メソッドが終了するようにプログラムを書きます。 スレッドの停止を他のスレッドから行う場合には、停止用のフラグ変数 を用意して、その変数を変更することによって、run() メソッドが終了 するようにします。 サンプルプログラムは P6 を参照してください。 参考記事 [JavaHouse-Brewers:6382]
[Q11]
Back
2つのスレッドで同期をとりたいのですが? [A-S019-11] Thread.join() メソッドを使います。 サンプルプログラムは P6 を参照してください。
[S019 Q-12]
Back
デーモンスレッド(deamon thread) を作成したいのですが? [S019 A-12] Thread.setDaemon(boolean on) メソッドを使って作成します。 スレッドは作成した時点ではユーザスレッドです。タイプを変更するの には、Thread.setDaemon(boolean on) メソッドの引数に true を指定しま す。 Java システムには、デーモンスレッドとユーザスレッドという2つのタ イプのスレッドがあります。デーモンスレッドは、ユーザスレッドの全 てが終了すると自動的に終了します。 Java Virtual Machine が作るデーモンスレッドの例としては、ガーベッ ジコレクションスレッドがあります。 参考記事 [JavaHouse-Brewers:15531]
[S019 Q-13]
Back
Thread.stop() を使わずに、スレッドを停止するにはどうすれば良いのですか? [S019 A-13] フラグを使用します。 サンプルプログラムは、P6 の TimerThread.java を参考にしてください。 この他、interrupt() メソッド、isInterrupted() メソッドを使用する 方法もあります。S019-14 を参考にしてください。 参考記事 [JavaHouse-Brewers:824],[JavaHouse-Brewers:6382] [JavaHouse-Brewers:7179],[JavaHouse-Brewers:13389] [JavaHouse-Brewers:13493],[JavaHouse-Brewers:14533] [JavaHouse-Brewers:22555],[JavaHouse-Brewers:22560] [JavaHouse-Brewers:22686],[JavaHouse-Brewers:22409] [JavaHouse-Brewers:22417]
[S019 Q-14]
Back
Thread.stop() メソッドが JDK1.2 で deprecated になっています。どう対処すればいいのですか? [S019 A-14] interrupt() メソッド、isInterrupted() メソッドを使用します。 while (true) { ... try { sleep(...); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } if (Thread.currentThread().isInterrupted()) { break; } } InterruptedException をキャッチした後に、interrupt() メソッドを呼 んでいるのは、InterruptedException はそのスレッドの interrupt 状態 をクリアしてしまうため、それに対する対処です。 フラグを使用する方法もあります。S019-13, P6 の TimerThread.java を 参考にしてください。サンプルを見ながらアプレットを作って、stop() メソッドを使っていた場合は、サンプルプログラム P7 を参照してくだ さい。 詳細な説明については、Java2 SDK の次のドキュメントが参考になるで しょう。 http://java.sun.com/products/jdk/1.2/docs/ または、 http://java.sun.com/products/jdk/1.2/ja/docs/ja/ 配下の guide/misc/threadPrimitiveDeprecation.html ドキュメントをダウンロードしているのであれば、そこに含まれています。 参考記事 [JavaHouse-Brewers:824],[JavaHouse-Brewers:6382] [JavaHouse-Brewers:7179],[JavaHouse-Brewers:13389] [JavaHouse-Brewers:13493],[JavaHouse-Brewers:14533] [JavaHouse-Brewers:22555],[JavaHouse-Brewers:22560] [JavaHouse-Brewers:22686],[JavaHouse-Brewers:22409] [JavaHouse-Brewers:22417]
[S019 Q-15]
Back
ThreadDeath 例外をキャッチすると、動作がおかしくなるのですが、なぜですか? [S019 A-15] ただキャッチしただけでは、スレッドが終了しないからです。 ThreadDeath 例外のインスタンスをキャッチする場合には、スレッドが実 際に終了するように、java.lang.ThreadDeath クラスのインスタンスを生 成しスローしなおします。 [参考] java.lang.Thread.stop() メソッドの呼び出しにより、 java.lang.ThreadDeath クラスのインスタンスは生成され、停止すべきス レッド(thread) にスローされます。特殊な場合を除いて、このインスタ ンスをキャッチする必要はありません。 キャッチしたインスタンスを破棄せず再度スローし直さないといけない という点から、java.lang.ThreadDeath クラスは java.lang.Exception ク ラスのサブクラスではなく、java.lang.Error クラスのサブクラスになっ ています。 参考記事 [JavaHouse-Brewers:13389],[JavaHouse-Brewers:13391]
[S019 Q-16]
Back
クラス設計で、Runnable を実装する方法と Thread を継承する方法とでは、どっちが良いのですか? [S019 A-16] Java(tm) House Mailing List Homepage の http://java-house.etl.go.jp/ml/archive/j-h-b/009449.html#bodyhttp://java-house.etl.go.jp/ml/archive/j-h-b/009577.html#body に非常に興味深い議論が交わされています。設計思想に関わる問題であ るので、簡単には結論を述べることができません。直接参照して、参考 にして下さい。 Sun Microsystems, Inc.が提供している Java Development Kit ドキュ メント (JDK 1.2) API と言語仕様に関するドキュメント +- Java プラットフォーム1.2 API 仕様 +- パッケージ java.lang +- Runnable インタフェース においては、「java.lang.Thread クラスのサブクラスを用意する方法 をとろうとしたときに、run メソッドだけオーバーライドするという 場合には、java.lang.Runnable インタフェースを使用してください」 というような内容の記述があります。 クラス設計について経験が浅いうちにはひとつの判断基準として使え ますが、先に示した議論を通して理解を深めると、単純にはそう言い 切れないことに気づくでしょう。 参考記事 [JavaHouse-Brewers:9449],[JavaHouse-Brewers:9577]
[S019 Q-17]
Back
単一のクラスに複数のスレッド(thread)を定義することはできるのでしょうか? [S019 A-17] スレッド(thread)にさせたい処理ごとに、java.lang.Thread クラスを継 承したクラスを複数用意しましょう。用意したクラスのインスタンスを 単一のクラスで生成すれば良いのです。 class ThreadA extends Thread { public void run() { /*処理A*/ } } class ThreadB extends Thread { public void run() { /*処理B*/ } } class MultiThread { Thread a; Thread b; public MultiThread() { a = new ThreadA(); b = new ThreadB(); a.start(); b.start(); } } 参考記事 [JavaHouse-Brewers:9448]
[S019 Q-18]
Back
複数のスレッド(thread)をまとめて stop できるのでしょうか? [S019 A-18] java.lang.ThreadGroup.interrupt() メソッドを利用すると、スレッドグ ループに登録されているすべてのスレッド(thread)の interrupt() メソッ ドが呼び出されます。これを利用して止めます。 まとめて停止したいスレッドは、次のように interrupt() メソッドをオー バーライドしておきます。 public class ThreadA extends Thread { boolean stop = false; ... public void interrupt() { super.interrupt(); stop = true; } public void run() { while (!stop) { // 処理 } } } 参考記事 [JavaHouse-Brewers:19131]
[S019 Q-19]
Back
new Thread(ThreadGroup, Runnable) を実行すると、IllegalThreadStateException が発生します。 [S019 A-19] その時点で引数の ThreadGroup が既に destroy されていると、 この現象が起きます。 参考記事 [JavaHouse-Brewers:19131]
[Q20]
Back
Thread.sleep(long) と Thread.interrupt() を使ってスレッド を止めたり動かしたりしているのですが、うまくいかない場合が 有ります。 [A-S019-20] sleep, interrupt ではなく、Object.wait(long), Object.notify() を 使うようにするとよいでしょう。 sleep, interrupt を使ったプログラムでは、タイミングが悪いとうまく いかないものになってしまう場合が有ります。 たとえば、止まるスレッドの方は、次のような感じのコードになってい ると思います。 if (寝るべきか?) { try { sleep(); } catch (InterruptException) { } } この場合 if のチェックと sleep の実行の間で“寝るべきでない”状況 に変化した時に、このスレッドは“寝るべきでない”にもかかわらず寝 てしまいます。 参考記事 [JavaHouse-Brewers:10694] ***************************************************************** ----------------------------------------------------------------- Appendix : 参考文献 ----------------------------------------------------------------- Java(tm) House Mailing List Homepage 以外に、次の文献を参考にしま した。 ・Java Development Kit ドキュメント (JDK 1.2) Sun Microsystems, Inc. ・Java スレッド プログラミング Scott Oaks, Henry Wong 著 戸松 豊和 監訳 西村 利浩 訳 オライリー・ジャパン ----------------------------------------------------------------- Appendix : サンプルプログラム ----------------------------------------------------------------- サンプルの動作確認環境: OS ... Vine Linux 2.0 CR Javaアプリケーション ... Java 2 SDK 1.2 for Linux Javaアプレット ... JavaVM on Netscape Communicator 4.7 (Netscape Communications Corporation-Java 1.1.5) ----------------------------------------------------------------- [P1] java.lang.Thread を使った例 次のThreadTest.java ファイルを作成し、javac でコンパイルします。 ====================================================== // ThreadTest.java public class ThreadTest { class Counter1 extends java.lang.Thread { public void run( ) { for (int i=0 ; i<10 ; i++) { System.out.println("Counter1: " + i); try { sleep(1000); } catch(java.lang.InterruptedException e) { } } } } class Counter2 extends java.lang.Thread { public void run( ) { for (int i=0 ; i<5 ; i++) { System.out.println("Counter2: " + i); try { sleep(2000); } catch(java.lang.InterruptedException e) { } } } } Counter1 counter1; Counter2 counter2; public ThreadTest() { counter1 = new Counter1(); counter2 = new Counter2(); } public void start() { counter1.start(); counter2.start(); } public static void main(String[] args) { ThreadTest test = new ThreadTest(); test.start(); } } ====================================================== この例では、1秒ごとに i の値をプリントするスレッド(thread)と、2秒 ごとに i の値をプリントするスレッドを用意し、並列に動作させていま す。 実行結果は、次の通りです。出力結果は微妙に変わる場合があります。 ====================================================== $ java ThreadTest Counter1: 0 Counter2: 0 Counter1: 1 Counter2: 1 Counter1: 2 Counter1: 3 Counter2: 2 Counter1: 4 Counter1: 5 Counter2: 3 Counter1: 6 Counter1: 7 Counter2: 4 Counter1: 8 Counter1: 9 $ ====================================================== ----------------------------------------------------------------- [P2] java.lang.Runnable を使った例 ポイントは、サンプル中の次の行です。 runner = new java.lang.Thread(this); runner.start(); java.lang.Thread のインスタンス runner 生成時に、java.lang.Runnable インタフェースを実装したクラスのインスタンス this を引数に指定して いることです。これにより、runner は、this.run() メソッドを呼び出す ことができるようになるのです。java.lang.Thread のインスタンス runner 生成後、並列処理とするために、runner の start メソッドを呼 び出しています。 1秒ごとに i の値を Java コンソールに出力するアプレットの例です。簡単 にアニメーションアプレットなどへ応用できるでしょう。 次の ThreadTestApplet.java ファイルを作成し、javac でコンパイルしま す。 ====================================================== // ThreadTestApplet.java public class ThreadTestApplet extends java.applet.Applet implements java.lang.Runnable { volatile java.lang.Thread runner; public void init() { runner = null; } public void start() { if (runner == null) { runner = new java.lang.Thread(this); runner.start(); } } public void run( ) { java.lang.Thread thisThread = java.lang.Thread.currentThread(); while (runner == thisThread) { for (int i=0 ; i<5 ; i++) { System.out.println("Count: " + i); try { thisThread.sleep(1000); } catch(java.lang.InterruptedException e) { } } } } public void stop() { runner = null; } } ====================================================== 実際に動作させるには、次のような HTML ファイルを用意し、 ThreadTestApplet.html として保存します。 Appletのrun() メソッドの実行結果は Java コンソールに出力されるので ブラウザで確認する場合は、Java コンソールを開いて下さい。 ====================================================== ====================================================== 次に、appletviewer での実行結果例を示します。appletviewer を終了す ると出力が停止します。 ====================================================== $ appletviewer ThreadTestApplet.html Count: 0 Count: 1 Count: 2 Count: 3 Count: 4 Count: 0 Count: 1 : : $ ====================================================== ----------------------------------------------------------------- [P5] 次の 3つのプログラムを作成します。 ====================================================== public class Counter extends java.lang.Thread { public void run( ) { for (int i=0 ; i<10 ; i++) { System.out.println("Counter: " + i); try { sleep(1000); } catch(java.lang.InterruptedException e) { } } } } ====================================================== public class RestartTest0 extends java.lang.Thread { public static void main(String[] args) { Counter cnt = new Counter(); cnt.start(); cnt.start(); } } ====================================================== public class RestartTest extends java.lang.Thread { public static void main(String[] args) { Counter cnt = new Counter(); for (int i=0 ; i<2 ; i++) { cnt.start(); try { sleep(11000); } catch (java.lang.InterruptedException e) { } } } } ====================================================== 実行結果 $ java RestartTest0 Exception in thread "main" Counter: 0 java.lang.IllegalThreadStateException at java.lang.Thread.start(Native Method) at RestartTest.main(RestartTest.java:7) Counter: 1 Counter: 2 Counter: 3 Counter: 4 Counter: 5 Counter: 6 Counter: 7 Counter: 8 Counter: 9 $ $ java RestartTest Counter: 0 Counter: 1 Counter: 2 Counter: 3 Counter: 4 Counter: 5 Counter: 6 Counter: 7 Counter: 8 Counter: 9 $ ====================================================== ----------------------------------------------------------------- [P6] 次の2つのプログラムを作成し、javacコマンドでコンパイルします。 ====================================================== public class JoinApplet extends java.applet.Applet { TimerThread timer; int x = 10; int y = 10; public void start() { if (timer == null) { timer = new TimerThread(this, 1000); } timer.start(); } public void stop() { timer.end(); try { timer.join(); System.out.println("JoinApplet stop."); } catch(java.lang.InterruptedException e) { } } public void paint(java.awt.Graphics g) { update(g); } public void update(java.awt.Graphics g) { y = y>90 ? 10 : y+10; g.clearRect(0, 0, 111, 111); g.drawLine(x, y, x+100, y); } } ====================================================== public class TimerThread extends java.lang.Thread { java.awt.Component com; volatile boolean runFlag; int interval; public TimerThread(java.awt.Component com, int interval) { super("TimerThread ("+interval+" milliseconds)"); com = com; this.interval = interval; runFlag = true; } public void run( ) { while (runFlag) { com.repaint(); try { Thread.sleep(interval); } catch(java.lang.InterruptedException e) { } System.out.println("TimerThread run."); } } public void end() { runFlag = false; } } ====================================================== 実際に動作させるには、次のような HTML ファイルを用意し、 ThreadTestApplet.html として保存します。 Applet の run() メソッドの実行結果は Java コンソールに出力されるので ブラウザで確認する場合は、Java コンソールを開いて下さい。 ====================================================== ====================================================== 次に、appletviewer での実行結果例を示します。appletviewer を 終了すると出力が停止します。 ====================================================== $ appletviewer JoinApplet.html TimerThread run. TimerThread run. TimerThread run. TimerThread run. TimerThread run. TimerThread run. TimerThread run. TimerThread run. TimerThread run. TimerThread run. TimerThread run. TimerThread run. TimerThread run. TimerThread run. JoinApplet stop. $ ====================================================== ----------------------------------------------------------------- [P7] java.lang.Runnable インタフェースを実装したアプレットプログラムで java.lang.Thread.stop() メソッドを使用していた場合の対処方法 ====================================================== // ThreadTestApplet.java -- Java 2 SDK より前のバージョン public class ThreadTestApplet extends java.applet.Applet implements java.lang.Runnable { volatile java.lang.Thread runner; public void init() { runner = null; } public void start() { if (runner == null) { runner = new java.lang.Thread(this); runner.start(); } } public void run( ) { java.lang.Thread thisThread = java.lang.Thread.currentThread(); while (true) { for (int i=0 ; i<5 ; i++) { System.out.println("Count: " + i); try { thisThread.sleep(1000); } catch(java.lang.InterruptedException e) { } } } } public void stop() { runner.stop(); runner = null; } } ====================================================== 上記の ThreadTestApplet.run(), ThreadTestApplet.stop() を、 次のように変更します。 ====================================================== // ThreadTestApplet.java -- Java 2 SDK以降 public class ThreadTestApplet extends java.applet.Applet implements java.lang.Runnable { volatile java.lang.Thread runner; public void init() { runner = null; } public void start() { if (runner == null) { runner = new java.lang.Thread(this); runner.start(); } } public void run( ) { java.lang.Thread thisThread = java.lang.Thread.currentThread(); while (runner == thisThread) { for (int i=0 ; i<5 ; i++) { System.out.println("Count: " + i); try { thisThread.sleep(1000); } catch(java.lang.InterruptedException e) { } } } } public void stop() { runner = null; } } ======================================================

Back
contributor: Hiroshi KOYAMA, Norikazu Nakato
コメントの送り先 Java FAQ BBS