1.2 查看编译统计
1.3 查看垃圾回收统计
说明:
S0C:第一个Survivor区的大小(KB)
S1C:第二个Survivor区的大小(KB)
S0U:第一个Survivor区的使用大小(KB)
S1U:第二个Survivor区的使用大小(KB)
EC:Eden区的大小(kB)
EU:Eden区的使用大小(KB)
OC:Old区的大小(KB)
OU:Old使用 大小(KB)
MC:方法大小(KB)
MU:方法去使用大小(KB)
CCSC:压缩类空间大小(KB)
CCSU:压缩类空间使用 大小(KB)
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收小号总时间
2. 通过jstack监控JVM当中线程的运行情况 jstack 进程ID
线程抢占CPU资源,当CPU过高时,定位线程,查看线程使用状态
2.1 线程状态:
初始状态:New, 线程对象创建出来后,没有调用start方法,线程处于初始状态
运行状态:
1.就绪状态:Readt 调用了start方法等待CPU分配资源
2.运行撞他:RUNNING CPU分配资源给该线程 该线程处于运行状态
阻塞状态:
线程获取资源,如果资源获取成功则正常运行,如果资源获取 失败,就处于阻塞状态
等待状态:线程手动调用wait( )方法,或者join( )方法,这些方法否是主动进入等待状态,等待状态会将CPU资源让渡
需要其他线程手动唤醒,notify(),notifyAll()唤起所有的等待线程
超时等待状态: TIMED_WAITING 与等待状态相同,都是主动进入等待,也是需要其他线程唤醒,
但是区别在与超时等待,如果超过了等待时间,则自动唤醒Thread.sleep(2000),
在休眠等待时间内会将CPU资源让渡,然后等待时间结束自动进入运行状态
终止状态DIED:线程结束之后的状态
3. 死锁问题
获取资源失败,导致应用程序的停止,我们可以借助jstack进行分析
3.1 模拟死锁
//定义资源 private static Object obj1=new Object(); private static Object obj2=new Object(); //线程a:先获取到资源1,然后休眠2s,在获取资源2 private static class ThreadA implements Runnable{ @Override public void run() { synchronized (obj1){ System.out.println("ThreadA获取到了obj1的资源~"); //休眠2s,因为我们要将CPU资源让渡出去,这样线程B就可以先抢占obj2的资源 try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (obj2){ System.out.println("ThreadA获取到了obj2资源~"); } } } } private static class ThreadB implements Runnable{ @Override public void run() { synchronized (obj2){ System.out.println("ThreadB获取到了obj2的资源~"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (obj1){ System.out.println("ThreadA获取到了obj1资源~"); } } } } public static void main(String[] args) { new Thread(new ThreadA()).start(); new Thread(new ThreadB()).start(); }
3.2 运行程序控制台效果
3.3 使用jstak进行分析
3.4 我们可以观察到