前回、
- JVMがアプリケーションを中断することなく実行できているか
- JVMがアプリケーションのリソースを奪っていないか
- OSのリソースが十分に割り当てられているか
- アプリケーションが動いているか
今回は、
「OSのリソースが十分に割り当てられているか」
3.では、
また、
スレッドの状態を4つに分ける
スレッドを見るにあたり、
- 処理の受付中
- 処理中
- 休み中
- 待機中
「処理の受付中」
「処理中」
「休み中」
「待機中」
OSのリソースが十分に割り当てられていないと、
また、
同じ理由で待機するスレッドが一定量を超えると、
スレッドが待機中になる3つの理由
スレッドは、
- I/
O待ち - ロック待ち中
- 委譲した処理の完了待ち
I/O待ち
ローカルやリモートのファイルを読み書きする時間や、
これらは、
ロック待ち
排他的に実行しないといけない処理の入口でスレッドが待たされている状態です。
スレッドは、
委譲した処理の完了待ち
同一のJVM内で別スレッドへ処理を委譲したり、
スレッドダンプでスレッドの状態を確認する
スレッドがどの処理中にどのような状態になっているかを確認するためには、
次のようなソースコードを例に、
public class ThreadStatusSample {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(1);
Future<String> future = executor.submit(() -> {
TimeUnit.MINUTES.sleep(1);
return "Hello";
});
System.out.println(future.get());
executor.shutdown();
}
}
mainメソッドは、
mainスレッドは、
次の図は、

スレッドダンプを取得する方法はさまざまありますが、
> jcmd <プロセスID> Thread.print "main" #1 prio=5 os_prio=0 tid=0x000000000271d800 nid=0x2ce4 waiting on condition [0x0000000002b5e000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000076b2f19b8> (a java.util.concurrent.FutureTask) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:429) at java.util.concurrent.FutureTask.get(FutureTask.java:191) at thread.ThreadStatusSample.main(ThreadStatusSample.java:28) "pool-1-thread-1" #11 prio=5 os_prio=0 tid=0x000000001db47800 nid=0xa18 waiting on condition [0x000000001e37f000] java.lang.Thread.State: TIMED_WAITING (sleeping) at java.lang.Thread.sleep(Native Method) at java.lang.Thread.sleep(Thread.java:340) at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386) at thread.ThreadStatusSample.lambda$main$0(ThreadStatusSample.java:14) at thread.ThreadStatusSample$$Lambda$1/990368553.call(Unknown Source) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) (略)
このスレッドダンプからは、
- mainスレッドは、
WAITING (parking)、 すなわち待機中である。具体的には、 Futureインターフェースの実体であるFutureTaskクラスのgetメソッド内でスレッドプールに委譲している処理が終わるのを、 sun. misc. Unsafeクラスのparkメソッドで待機中である - pool-1-thread-1スレッドは、
TIMED_ WAITING (sleeping)、 すなわち休み中である。具体的には、 TimeUnitクラスのsleepメソッド内でThreadクラスのsleepメソッドを呼び出して、 休み中である
スレッドダンプでは、
ただし、

最初の3回は、
予測を誤らないためには、
- スレッドダンプをより細かい周期で取得する
- (負荷がかかりますが)
JVMへ接続してスレッドの変化をすべて記録する
しかし、
次回は、