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

【参考】