zoukankan      html  css  js  c++  java
  • 线程dump

    当应用程序运行变慢或者发生故障时,可能通过分析java的Thread Dumps得到分析他们得到阻塞和存在瓶颈的线程。

    线程堆栈是虚拟机中线程(包括锁)状态的一个瞬间状态的快照,即系统在某一个时刻所有线程的运行状态,包括每一个线程的调用堆栈,锁的持有情况。主要包含的信息包括

      1、线程名字,id,线程的数量等。

       2、线程的运行状态,锁的状态(锁被哪个线程持有,哪个线程在等待锁等)

       3、调用堆栈包含完整的类名,所执行的方法,源代码的行数等

       线程栈是瞬时快照包含线程状态以及调用关系,可以借助堆栈信息帮助分析很多性能问题。线程栈是瞬时记录,所以没有历史消息的回溯,经常需要打印几次做对比分析,并且在一般情况下都需要结合应用程序的日志进行问题定信。

    1、系统cpu过高
    2、性能瓶颈:如响应时间长但CPU资源并不高
    3、系统运行越来越慢,响应时间长
    4、系统挂起,长时间无响应或响应时间长
    5、线程死锁,死循环等
    6、由于线程数量太多导致的内存溢出(如无法创建线程等)

    Java线程原理

        线程同步

         多条线程之间可以同时执行,为了确保多线程在使用共享资源上面的通用性,使用线程同步保证在同一时间只能有一条线程可以访问共享资源。

         线程同步在Java中可以使用监视器。每个Java对象都有一个监视器,这个监视器只能被一个线程拥有。当一个线程要获得另外线程拥有的监视器时,需要进入等待队列直到线程释放监视器。

        线程的状态

        为了分析Thread Dump ,需要先了解线程的状态。线程的状态是在java.lang.Thread.State中。

     

     

    1. 新建状态(New) 新创建了一个线程对象。

    2. 就绪状态(Runnable) 线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。

    3. 运行状态(Running) 就绪状态的线程获取了CPU,执行程序代码。

    4. 阻塞状态(Blocked) 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:

    • 等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
    • 同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
    • 其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

    5. 死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

    Jstack使用的关键字描述的线程状态与上边线程不太一样,所以可能理解上可能会出现混淆。虽然Java中的线程一样有上述中描述的5种状态,但在实际情况下线程新建状态和死亡状态持续很短,我们也并不太关心。大多时候我们关注的是运行状态/阻塞状态,

     

     

    详细过程可参考:

    • 当执行new Thread(Runnabler)后,新创建出来的线程处于new状态,这种线程不可能执行
    • 当执行thread.start()后,线程处于runnable状态,这种情况下只要得到CPU,就可以开始执行了。runnable状态的线程,会接受JVM的调度,进入running状态,但是具体何时会进入这个状态,是随机不可知的
    • running状态中的线程最为复杂,可能会进入runnable、waiting、timed_waiting、blocked、dead状态:
      • 如果CPU调度给了别的线程,或者执行了Thread.yield()方法,则进入runnable状态,但是也有可能立刻又进入running状态
      • 如果执行了Thread.sleep(long),或者thread.join(long),或者在锁对象上调用object.wait(long)方法,则会进入timed_waiting状态
      • 如果执行了thread.join(),或者在锁对象上调用了object.wait()方法,则会进入waiting状态
      • 如果进入了同步方法或者同步代码块,没有获取锁对象的话,则会进入blocked状态
      • 处于waiting状态中的线程,如果是因为thread.join()方法进入等待的,在目标thread执行完毕之后,会回到runnable状态;如果是因为object.wait()方法进入等待的话,在锁对象执行object.notify()或者object.notifyAll()之后会回到runnable状态
      • 处于timed_waiting状态中的线程,和waiting状态中的差不多,只不过是设定时间到了,就会回到runnable状态
      • 处于blocked状态中的线程,只有获取了锁之后,才会脱离阻塞状态
      • 当线程执行完毕,或者抛出了未捕获的异常之后,会进入dead状态,该线程结束

     

     

    我们需要重点关注RUNNABLE、BLOCKED、WAITING和TIME_WAITING四种状态,jstack打印的线程堆栈中也会时时出现。

    1)BLOCKED:就是线程在等待获取锁进入同步块或者同步方法中。两个死锁的线程即是Blocked。

    2)WAITING:比BLOCKED状态进步一些,指已经获得锁了,但由于有些条件不满足,要自己等会,调用object.wait()方法。等条件满足了,别的线程调用notify再叫我。另外也可以调用Thread.join()方法,顾名思义就是调用别的线程的join方法,让别人join进来先执行,那我就只能等会了。但是由于wait()和notify()以及notifyAll()用于协调对共享资源的存取,所以必须在synchronized块中使用。所以即便wait状态的线程被notfiy唤醒了,也需要再次获得锁,所以唤醒后进入Blocked状态。

    3)TIMED_WAITING:类比WAITING,差异是不需要notify()或者notifyAlL()方法唤醒,时间到了自己醒了。另外sleep比较好理解,就是让当前线程睡一会,与wait的区别是它不释放锁

    4)RUNNABLE不用多说,在JAVA虚拟机中已经在运行,但是在等待操作系统资源,比如CPU时间片。

    相关链接:

    https://blog.csdn.net/rachel_luo/article/details/8920596

    https://blog.csdn.net/zxp_cpinfo/article/details/54971115

  • 相关阅读:
    document.getElementById("mytxt").style.left=""style.left在IE的FF中注意
    asp.net 用户控件中 使用相对路径的解决方法 图片路径问题(用户控件、图片路径) ,ResolveUrl
    探索 Block (一) (手把手讲解Block 底层实现原理)
    iOS 多线程开发 (概念与API简介)
    iOS 性能小点
    iOS runtime (二)(runtime学习之AutoCoding源码分析)
    探索 NSRunLoop (二)(NSRunLoop 自己动手实现SimpleRunLoop)
    iOS NSNotificationCenter (自己实现一个通知中心XMCNotificationCenter)
    iOS runtime (三)(runtime学习之YYModel源码分析)
    iOS runtime(一)(runtime 分析理解)
  • 原文地址:https://www.cnblogs.com/ken-jl/p/8999144.html
Copyright © 2011-2022 走看看