logo

スレッドのライフサイクル (スレッド状態)

Java では、スレッドは常に次のいずれかの状態で存在します。これらの状態は次のとおりです。

  1. 新しい
  2. アクティブ
  3. ブロック/待機中
  4. 時間制限付き待機
  5. 終了しました

さまざまなスレッド状態の説明

新しい: 新しいスレッドが作成されると、常に新しい状態になります。新しい状態のスレッドの場合、コードはまだ実行されていないため、実行は開始されていません。

アクティブ: スレッドが start() メソッドを呼び出すと、新しい状態からアクティブ状態に移行します。アクティブ状態には 2 つの状態が含まれます。1 つは 実行可能 、そしてもう一つは ランニング

    実行可能:実行の準備ができたスレッドは、実行可能状態に移行します。実行可能状態では、スレッドが実行中であるか、任意の時点で実行の準備ができている可能性があります。スレッドの実行時間を提供する、つまりスレッドを実行状態に移行するのは、スレッド スケジューラの義務です。
    マルチスレッドを実装するプログラムは、個々のスレッドごとに一定の時間を取得します。それぞれのスレッドは短期間実行され、割り当てられたタイム スライスが終了すると、スレッドは自発的に CPU を他のスレッドに放棄し、他のスレッドもその時間スライスの間実行できるようになります。このようなシナリオが発生するたびに、実行を希望するスレッドはすべて、実行の順番を待って実行可能な状態になります。実行可能状態では、スレッドが存在するキューが存在します。ランニング:スレッドが CPU を取得すると、実行可能状態から実行状態に移行します。一般に、スレッドの状態の最も一般的な変化は、実行可能から実行可能になり、再び実行可能に戻ることです。

ブロックまたは待機中: スレッドが一定期間 (永続的ではなく) 非アクティブになると、そのスレッドはブロックされた状態になるか、待機状態になります。

たとえば、スレッド (名前を A としましょう) は、プリンターからデータを印刷したいと考えている場合があります。ただし、同時に、他のスレッド (名前を B としましょう) がプリンターを使用してデータを印刷しています。したがって、スレッド A は、スレッド B がプリンタを使用するまで待機する必要があります。したがって、スレッド A はブロックされた状態になります。ブロック状態のスレッドは実行を実行できないため、中央処理装置 (CPU) のサイクルを消費することはありません。したがって、スレッド スケジューラが待機状態またはブロック状態にあるスレッド A を再アクティブ化するまで、スレッド A はアイドル状態のままであると言えます。

メインスレッドが join() メソッドを呼び出すとき、メインスレッドは待機状態にあると言われます。メインスレッドは、子スレッドがタスクを完了するまで待機します。子スレッドがジョブを完了すると、メイン スレッドに通知が送信され、スレッドは再び待機状態からアクティブ状態に移行します。

待機中またはブロック状態のスレッドが多数ある場合、どのスレッドを選択し、どのスレッドを拒否するかを決定するのはスレッド スケジューラの役割であり、選択されたスレッドには実行の機会が与えられます。

時間指定待機: 時には、待っていると飢餓につながることもあります。たとえば、スレッド (名前は A) がコードのクリティカル セクションに入ったが、そのクリティカル セクションから出ようとしません。このようなシナリオでは、別のスレッド (名前は B) が永遠に待機する必要があり、飢餓が発生します。このようなシナリオを回避するために、スレッド B には時限待機状態が与えられます。したがって、スレッドは永遠ではなく、特定の期間待機状態になります。時間指定待機の実際の例は、特定のスレッドで sleep() メソッドを呼び出す場合です。 sleep() メソッドは、スレッドを時間指定された待機状態にします。時間が経過すると、スレッドが起動し、以前に終了したときから実行を開始します。

終了: スレッドは次の理由で終了状態に達します。

  • スレッドがジョブを完了すると、スレッドは存在するか、正常に終了します。
  • 異常終了:これは、ハンドルされない例外やセグメンテーション違反などの異常なイベントが発生したときに発生します。

終了したスレッドは、そのスレッドがシステム内に存在しないことを意味します。言い換えれば、スレッドは死んでいるので、死んだスレッドを再生成する (強制終了後にアクティブになる) ことはできません。

次の図は、スレッドのライフサイクルに関係するさまざまな状態を示しています。

Java スレッドのライフサイクル

スレッド状態の実装

Java では、次を使用してスレッドの現在の状態を取得できます。 Thread.getState() 方法。の java.lang.Thread.State Java のクラスは、スレッドの状態を表す定数 ENUM を提供します。これらの定数は次のとおりです。

ユーザー名とは何ですか
 public static final Thread.State NEW 

これは、スレッドの最初の状態である NEW 状態を表します。

 public static final Thread.State RUNNABLE 

これは実行可能な状態を表します。スレッドがキュー内で実行を待っていることを意味します。

 public static final Thread.State BLOCKED 

ブロックされた状態を表します。この状態では、スレッドはロックの取得を待機しています。

 public static final Thread.State WAITING 

待機状態を表します。スレッドは、タイムアウトなしで Object.wait() メソッドまたは Thread.join() メソッドを呼び出すと、この状態になります。待機状態のスレッドは、別のスレッドがタスクを完了するのを待っています。

 public static final Thread.State TIMED_WAITING 

時間指定された待機状態を表します。待機と時間指定待機の主な違いは、時間の制約です。待機には時間の制約がありませんが、時間指定待機には時間の制約があります。次のメソッドを呼び出すスレッドは、時間指定された待機状態に達します。

  • 寝る
  • タイムアウト付きで参加する
  • タイムアウトして待つ
  • 公園まで
  • パークナノス
 public static final Thread.State TERMINATED 

これは、終了または停止したスレッドの最終状態を表します。終了したスレッドは、その実行が完了したことを意味します。

スレッド状態をデモするための Java プログラム

次の Java プログラムは、上で定義したスレッドの状態の一部を示しています。

ファイル名: スレッド状態.java

 // ABC class implements the interface Runnable class ABC implements Runnable { public void run() { // try-catch block try { // moving thread t2 to the state timed waiting Thread.sleep(100); } catch (InterruptedException ie) { ie.printStackTrace(); } System.out.println('The state of thread t1 while it invoked the method join() on thread t2 -'+ ThreadState.t1.getState()); // try-catch block try { Thread.sleep(200); } catch (InterruptedException ie) { ie.printStackTrace(); } } } // ThreadState class implements the interface Runnable public class ThreadState implements Runnable { public static Thread t1; public static ThreadState obj; // main method public static void main(String argvs[]) { // creating an object of the class ThreadState obj = new ThreadState(); t1 = new Thread(obj); // thread t1 is spawned // The thread t1 is currently in the NEW state. System.out.println('The state of thread t1 after spawning it - ' + t1.getState()); // invoking the start() method on // the thread t1 t1.start(); // thread t1 is moved to the Runnable state System.out.println('The state of thread t1 after invoking the method start() on it - ' + t1.getState()); } public void run() { ABC myObj = new ABC(); Thread t2 = new Thread(myObj); // thread t2 is created and is currently in the NEW state. System.out.println('The state of thread t2 after spawning it - '+ t2.getState()); t2.start(); // thread t2 is moved to the runnable state System.out.println('the state of thread t2 after calling the method start() on it - ' + t2.getState()); // try-catch block for the smooth flow of the program try { // moving the thread t1 to the state timed waiting Thread.sleep(200); } catch (InterruptedException ie) { ie.printStackTrace(); } System.out.println('The state of thread t2 after invoking the method sleep() on it - '+ t2.getState() ); // try-catch block for the smooth flow of the program try { // waiting for thread t2 to complete its execution t2.join(); } catch (InterruptedException ie) { ie.printStackTrace(); } System.out.println('The state of thread t2 when it has completed it's execution - ' + t2.getState()); } } 

出力:

 The state of thread t1 after spawning it - NEW The state of thread t1 after invoking the method start() on it - RUNNABLE The state of thread t2 after spawning it - NEW the state of thread t2 after calling the method start() on it - RUNNABLE The state of thread t1 while it invoked the method join() on thread t2 -TIMED_WAITING The state of thread t2 after invoking the method sleep() on it - TIMED_WAITING The state of thread t2 when it has completed it's execution - TERMINATED 

説明: 新しいスレッドを生成するたびに、そのスレッドは新しい状態になります。メソッド start() がスレッド上で呼び出されると、スレッド スケジューラはそのスレッドを実行可能な状態に移行します。いずれかのスレッド インスタンスで join() メソッドが呼び出されるたびに、そのステートメントを実行している現在のスレッドは、このスレッドが実行を終了するまで待機する必要があります。つまり、スレッドが終了状態に移行する必要があります。したがって、最後の print ステートメントがコンソールに出力される前に、プログラムはスレッド t2 でメソッド join() を呼び出し、スレッド t2 が実行を終了するまでスレッド t1 を待機させ、スレッド t2 は終了状態またはデッド状態になります。 。スレッド t1 は、スレッド t2 でメソッド join() を呼び出したため、スレッド t2 の実行が終了するのを待っているため、待機状態になります。