Javaのスレッドの生存状態を確認する
Javaのスレッドの生存状態を確かめてみたメモです。
Javaのスレッドの生存状態をThreadとExecutorServiceのメソッドで確認してみました。
(スレッドダンプによる生存状態の確認は試してないです)
Thread.isAlive()
Thread.isAlive()はスレッドが起動して生存している場合、trueを返します。
確認用に0から4までカウントアップする下記のタスクを用意。
MyTask.java
public static class MyTask implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName() + " START"); int count = 0; for (int i = 0; i < 5; i ++) { try { System.out.println(count); count++; Thread.sleep(500L); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + " END"); } }
タスク実行中と実行後のisAlive()の結果を標準出力してみます。
ThreadIsAliveMain.java
public class ThreadIsAliveMain { public static void main(String[] args) throws InterruptedException { Thread myTask = new Thread(new MyTask()); myTask.start(); while (true) { System.out.println("isAlive: " + myTask.isAlive()); Thread.sleep(1_000L); } } }
実行結果
isAlive: true Thread-0 START 0 1 isAlive: true 2 3 isAlive: true 4 Thread-0 END isAlive: false
スレッドがタスクを実行中はtrueになっていて、タスク終了後はfalseになっているのが分かります。
Thread.getState()
Thread.getState()はスレッドの状態を返します。
戻り値はThread.StateのEnumです。
下記6つの状態があります。
NEW | まだ起動してないスレッド |
RUNNABLE | 実行中のスレッド |
BLOCKED | ブロックされてモニターロック待機中のスレッド |
WAITING | 待機中のスレッド |
TIMED_WAITING | 指定された待機時間、待機中のスレッド |
TERMINATED | 終了したスレッド |
タスク実行中と実行後のgetState()の結果を標準出力してみます。
ThreadGetState.java
public class ThreadGetState { public static void main(String[] args) throws InterruptedException { Thread myTask = new Thread(new ThreadIsAliveMain.MyTask()); myTask.start(); while (true) { Thread.State state = myTask.getState(); System.out.println("state: " + state.name()); Thread.sleep(1_000L); } } }
実行結果
state: RUNNABLE Thread-0 START 0 1 state: TIMED_WAITING 2 3 state: TIMED_WAITING 4 Thread-0 END state: TERMINATED state: TERMINATED
タスク実行直後はRUNNABLEで実行状態になっており、
その後はsleep()でTIMED_WAITINGになっています。
タスク終了後はTERMINATEDで終了状態になっています。
Thread.join()
Thread.join()でスレッドが終了するのを待機します。
タスク実行直後とjoin()後のスレッドの状態を確認してみます。
ThreadJoinMain.java
public class ThreadJoinMain { public static void main(String[] args) throws InterruptedException { Thread myTask = new Thread(new ThreadIsAliveMain.MyTask()); myTask.start(); System.out.println("isAlive: " + myTask.isAlive()); System.out.println("state: " + myTask.getState().name()); myTask.join(); System.out.println("isAlive: " + myTask.isAlive()); System.out.println("state: " + myTask.getState().name()); } }
実行結果
isAlive: true Thread-0 START 0 state: RUNNABLE 1 2 3 4 Thread-0 END isAlive: false state: TERMINATED
タスク実行後はRUNNABLEで実行状態になっており、
join()後はTERMINATEDで終了状態になっています。
ExecutorService.isShutdown(), ExecutorService.isTerminated()
ExecutorService.isShutdown()はシャットダウン状態の場合trueを返します。
ExecutorService.shutdown()が呼ばれるとシャットダウン状態になりますが、すぐに終了状態になるわけではなく、
終了処理に入ります。
スレッドが終了しているかを確認するにはExecutorService.isTerminated()で確認します。
ExecutorService.isTerminated()はスレッドが終了状態の場合trueを返します。
確認用に数字をカウントアップするタスクを用意。
CountTask.java
public class CountTask implements Runnable { private int count; public CountTask(int count) { this.count = count; } @Override public void run() { for(int i = 0; i < count; i++) { try { Thread.sleep(400L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread() + " : " + i); } } }
シングルスレッドで確認してみます。
NewSingleThreadExecutorTerminateMain.java
public class NewSingleThreadExecutorTerminateMain { public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newSingleThreadExecutor(); executorService.execute(new CountTask(4)); System.out.println("isShutdown: " + executorService.isShutdown()); System.out.println("isTerminated: " + executorService.isTerminated()); Thread.sleep(1_000L); executorService.shutdown(); System.out.println("isShutdown: " + executorService.isShutdown()); System.out.println("isTerminated: " + executorService.isTerminated()); Thread.sleep(1_000L); System.out.println("isShutdown: " + executorService.isShutdown()); System.out.println("isTerminated: " + executorService.isTerminated()); } }
実行結果
isShutdown: false isTerminated: false Thread[pool-1-thread-1,5,main] : 0 Thread[pool-1-thread-1,5,main] : 1 isShutdown: true isTerminated: false Thread[pool-1-thread-1,5,main] : 2 Thread[pool-1-thread-1,5,main] : 3 isShutdown: true isTerminated: true
タスク実行中はisShutdown(),isTerminated()ともにfalseです。
shutdown()実行直後はisShutdown()はtrueになっていますが、まだタスクが完全に終了していないため、
isTerminated()はfalseになっています。
1秒スリープした後はタスクが完了しており、どちらもtrueになっていることが分かります。
2スレッドのスレッドプールでも確認してみます。
1つのスレッドは0~3までカウントアップし、
もう1つのスレッドは0~5までカウントアップします。
NewFixedThreadPoolTerminatedMain.java
public class NewFixedThreadPoolTerminatedMain { public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool(2); executorService.execute(new CountTask(4)); executorService.execute(new CountTask(6)); System.out.println("isShutdown: " + executorService.isShutdown()); System.out.println("isTerminated: " + executorService.isTerminated()); Thread.sleep(1_000L); executorService.shutdown(); System.out.println("isShutdown: " + executorService.isShutdown()); System.out.println("isTerminated: " + executorService.isTerminated()); Thread.sleep(1_000L); System.out.println("isShutdown: " + executorService.isShutdown()); System.out.println("isTerminated: " + executorService.isTerminated()); Thread.sleep(1_000L); System.out.println("isShutdown: " + executorService.isShutdown()); System.out.println("isTerminated: " + executorService.isTerminated()); } }
実行結果
isShutdown: false isTerminated: false Thread[pool-1-thread-2,5,main] : 0 Thread[pool-1-thread-1,5,main] : 0 Thread[pool-1-thread-2,5,main] : 1 Thread[pool-1-thread-1,5,main] : 1 isShutdown: true isTerminated: false Thread[pool-1-thread-2,5,main] : 2 Thread[pool-1-thread-1,5,main] : 2 Thread[pool-1-thread-2,5,main] : 3 Thread[pool-1-thread-1,5,main] : 3 isShutdown: true isTerminated: false Thread[pool-1-thread-2,5,main] : 4 Thread[pool-1-thread-2,5,main] : 5 isShutdown: true isTerminated: true
一方のスレッドが完了しただけではisTerminated()はtrueとならず、
すべてのスレッドが完了するとisTerminated()がtrueとなることが分かります。
終わり。
ソースは下記にあげました。
github.com
【参考】