如果“内存”页签相当于可视化的jstat命令的话,“线程”页签的功能相当于可视化的jstack命令,遇到线程停顿时可以使用这个页签进行监控分析。
线程长时间停顿的主要原因主要有:等待外部资源(数据库连接,网络资源,设备资源等),死循环,锁等待(活锁和死锁)。通过代码清单分别演示一下这几种情况
程序运行后,首先“线程”页签选择main线程,如图4-7所示。堆栈追踪显示BufferedRcader在readBytes方法
接着监控testBusyThread线程,如图4-8所示,testBusyThread线程一直在执行空循环,从堆栈追踪中看到一直在MonitoringTest.java代码的41行停留,41行为:while(true)。这时候线程为Runnable状态,而且没有归还线程执行令牌的动作,会在空循环上用尽全部执行时间直到线程切换,这种等待会消耗较多的CPU资源。
图4-9显示testLockThread线程在等待着lock对象的notify或notifyAll方法的出现,线程这时候处于WAITING状态,在被唤醒前不会被分配执行时间。
testLockThread线程正在处于正常的活锁等待,只要lock对象的notify()或notifyAll()方法被调用,这个线程便能继续执行。代码4-10演示了一个无法再被**的死锁等待。