![]() ![]() ![]() ![]() |
スレッドの制御 |
次の図が示しているのは、Java スレッドがその生きている間のいかなる時にも存在できるさまざまな状態であり、メソッド呼び出しが別の状態への移行をもたらす状態である。 この図は完全な有限状態の図ではなく、むしろスレッドの生きている間についてのより興味深くて一般的な事実の概略である。 このページでは、Thread のライフサイクルの状態に関して説明する。
新規のスレッド
次の文は新規のスレッドを作成するが、図の中では「新規のスレッド(New Thread)」というラベル付きの状態でスレッドを出るため、開始はしない。スレッドが「新規のスレッド」状態にある時、それはただ空の Thread オブジェクトである。 システム資源はまだ割り当てられていない。 したがって、スレッドがこの状態にある時は、ただスレッドを開始したり中止することができるだけである。スレッドがこの状態にある時にThread myThread = new MyThreadClass();start()
あるいはstop()
に加えて他のメソッドを呼び出すことは、意味をなさず、 IllegalThreadStateException を引き起こす。実行可能
では、次の2つのコードを考えてみる。Thread myThread = new MyThreadClass(); myThread.start();start()メソッド
は、スレッドの実行に必要なようにシステム資源を作成し、実行するためにスレッドを予定し、スレッドのrun()
メソッドを呼び出す。 この時点でスレッドは「 実行可能な(Runnable) 」状態にある。 スレッドがこの状態にある時に実際にスレッドが実行していないこともあるので、この状態は「実行中」よりどちらかと言うと、「実行可能な」と呼ばれる。 多くのコンピュータが、同時にすべての「実行可能な」スレッドの実行を不可能にするシングルプロセッサを持っている。 これにより、 Java 実行時システムは、すべての「実行可能な」スレッド間でプロセッサを共有するスケジューリングスキーマを実装しなくてはならない。 (スケジューリングの詳細については、スレッドの優先順位 を参照のこと。) しかし、ほとんどの用途では「実行可能な」状態を単に「実行中」と考えることができる。 スレッドが実行中、つまり「実行可能」でありかつ現スレッドである時は、run()
メソッドの命令は連続的に実行している。実行不可能
以下の 4 つのイベントの1つが発生すると、スレッドが「実行不可能な(Not Runnable)」状態に入る。
- 誰かが
suspend()
メソッドを起動する
- 誰かが
sleep()
メソッドを起動する
- スレッドが条件変数に応対する
wait()
メソッドを使用する
- スレッドが入出力ではブロックしている
例えば、このコードの太字の行は、10 秒(10,000ミリ秒)間スリープするためにThread myThread = new MyThreadClass(); myThread.start(); try { myThread.sleep(10000); } catch (InterruptedException e){ }myThread
を置く。 この 10 秒間に、たとえプロセッサが使用可能になっても、myThread
は実行しないであろう。 10 秒後にmyThread
が再度「実行可能」になり、そのときプロセッサが使用可能になれば、myThread
は実行する。上記に表示した「実行不可能な」状態のそれぞれの「エントランス」については、「実行可能な」状態にスレッドを返す特定の明確な非難経路がある。 非難経路は対応する「エントランス」のためにのみ動作する。 例えば、もしスレッドがスリープするために置かれたら、指定された長さのミリ秒が経過しないと、スレッドは再度「実行可能」にならない。 スリープしているスレッドでは
resume()
を呼び出しても効果がない。次は、すべてのエントランスの「実行不可能な」状態への非難経路を示す。
- スレッドがスリープするために置かれると、指定された長さのミリ秒が経過しなくてはならない。
- スレッドが一時停止すると、誰かがその
resume()
メソッドを呼び出さなくてはならない。
- スレッドが条件変数に応対しているなら、変数を所有するどんなオブジェクトでも
notify()
あるいはnotifyAll()
を呼び出して、それを放棄しなくてはならない。
- スレッドが入出力でブロックされるなら、指定された入出力コマンドは完結しなくてはならない。
死んでいる
スレッドは、自然死あるいは終了(停止)の2つの方法で消えることができる。run()
メソッドが正常に終了すると、スレッドは当然消える。 例えば、次のメソッドのwhile
ループは有限のループである。100 回繰り返して、終了する。このpublic void run() { int i = 0; while (i < 100) { i++; System.out.println("i = " + i); } }run()
メソッドを持つスレッドは、当然ループの後に消えて、run()
メソッドは完結する。
stop() メソッド
を呼び出すことによりいつでもスレッドも終了することができる。 次のコードの一部は、Thread myThread = new MyThreadClass(); myThread.start(); try { Thread.currentThread().sleep(10000); } catch (InterruptedException e){ } myThread.stop();myThread
を作成して開始し、現在のスレッドを 10 秒間スリープさせる。 現在のスレッドが呼び起こされると、コードの太字の行はmyThread
を終了する。
stop()
メソッドは、終了するためにスレッドで ThreadDeath オブジェクトをあげる。 したがって、スレッドが終了すると、この方法でスレッドは非同期に消える。 スレッドは、実際に ThreadDeath 例外割り込みを受け取ると、終了する。アプレットは、実行中の Java 互換のブラウザがアプレットに停止を示すと(ユーザが例えばページを変更する時)、そのスレッドのすべてを終了するために
stop()メソッド
を使用する。 詳細については、アプレットでのスレッドを参照のこと。
IllegalThreadStateException
実行時システムは、スレッドでメソッドを呼び出し、しかもスレッドの状態によってメソッド呼び出しができないと、 IllegalThreadStateException をあげる。 例えば、 IllegalThreadStateException は、「実行可能」でないスレッドでsuspend()
を呼び出す時にあげられる。これまでのレッスンでさまざまなスレッドの例を示したように、例外をあげることができるスレッドメソッドを呼び出すと、例外割り込みをキャッチして処理するか、あるいは呼び出しているメソッドがキャッチできない例外割り込みをあげると宣言しなくてはならない。
isAlive() メソッド
isAlive() メソッドは、スレッドの状態に関する最後のワードである。Thread クラスのプログラム作成インタフェースはisAlive()
と呼ばれるメソッドを含む。isAlive()
は、もしスレッドが開始されて、停止されていなかったなら、 true を返す。 したがって、もしisAlive()
メソッドが false を返したら、スレッドが「新規のスレッド」あるいは「死んでいる」であることがわかる。 もしisAlive()
メソッドが true を返したら、スレッドが「実行可能」あるいは「実行不可能」であることがわかる。 「新規のスレッド」と「死んでいる」スレッドを区別することはできない。同様に「実行可能な」スレッドと「実行不可能な」スレッドを区別することもできない。参照
java.lang.Thread
java.lang.IllegalThreadStateException
java.lang.ThreadDeath
![]() ![]() ![]() ![]() |
スレッドの制御 |