线程dump详解

Java中的线程是内核线程和用户线程一起实现的,状态图(参见java.lang.Thread,实际上只有6个状态,为了更好理解线程状态,图中添加了不存在的状态Running)如下:

线程dump详解_第1张图片

   很多时候,我们系统出现:线程阻塞、死锁、不能创建更多本地线程的OOME、CPU消耗过多等等;甚至有些堆内存溢出也可能跟线程有关,因为可能是创建了过多的线程导致堆内存不够用。问题排查需要深入到线程的dump信息中:

   常见问题排查工具:jstack命令 或者 JvisualVM或其他第三方工具

为了更好地分析线程dump信息,举个栗子:5线程交替打印123456789...100000,程序如下:

package com.ali.review;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;

/**
 * Created by lucene on 2017/6/14.
 */
public class PrintDataThread implements Runnable {
    private int max;
    private AtomicInteger counter;
    private int mod;
    private int remainder;
    Condition condition;

    public PrintDataThread(int max, AtomicInteger counter, int mod, int remainder) {
        this.max = max;
        this.counter = counter;
        this.mod = mod;
        this.remainder = remainder;
    }

    public void run() {
        while (counter.get() < max) {
            synchronized (counter) {
                if ((counter.get() % mod) == remainder && counter.get() < max) {
                    int currentNum = counter.addAndGet(1);
                    System.out.println("Thread " + Thread.currentThread().getId() + "-----" + currentNum);
                    counter.notifyAll();
                }else{
                    try {
                        counter.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
package com.ali.review;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by lucene on 2017/6/14.
 */
public class PrintDataMain {

    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newFixedThreadPool(5);
        AtomicInteger counter = new AtomicInteger(0);
        int max = 100000;
        int mod = 5;
        long before = System.currentTimeMillis();
        for (int i = 0; i < mod; i++) {
            threadPool.execute(new PrintDataThread(max, counter, mod, i));
        }
        threadPool.shutdown();
        while (!threadPool.isTerminated()) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.println(System.currentTimeMillis() - before);
    }
}

运行结果:

。。。
Thread 10-----99981
Thread 11-----99982
Thread 12-----99983
Thread 13-----99984
Thread 14-----99985
Thread 10-----99986
Thread 11-----99987
Thread 12-----99988
Thread 13-----99989
Thread 14-----99990
Thread 10-----99991
Thread 11-----99992
Thread 12-----99993
Thread 13-----99994
Thread 14-----99995
Thread 10-----99996
Thread 11-----99997
Thread 12-----99998
Thread 13-----99999
Thread 14-----100000

 

线程dump信息


2017-06-18 00:15:44
Full thread dump Java HotSpot(TM) 64-Bit Server VM (24.75-b04 mixed mode):

"RMI TCP Connection(2)-192.168.0.100" daemon prio=6 tid=0x000000000ac7f000 nid=0x1110 runnable [0x000000000c7ad000]
   java.lang.Thread.State: RUNNABLE
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.read(SocketInputStream.java:152)
	at java.net.SocketInputStream.read(SocketInputStream.java:122)
	at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
	at java.io.BufferedInputStream.read(BufferedInputStream.java:254)
	- locked <0x00000000c15780d0> (a java.io.BufferedInputStream)
	at java.io.FilterInputStream.read(FilterInputStream.java:83)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:549)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:828)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.access$400(TCPTransport.java:619)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$1.run(TCPTransport.java:684)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$1.run(TCPTransport.java:681)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:681)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
	- <0x00000000c1536d98> (a java.util.concurrent.ThreadPoolExecutor$Worker)

"JMX server connection timeout 19" daemon prio=6 tid=0x000000000aceb800 nid=0x1c24 in Object.wait() [0x000000000c4ae000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	at com.sun.jmx.remote.internal.ServerCommunicatorAdmin$Timeout.run(ServerCommunicatorAdmin.java:168)
	- locked <0x00000000c15328b8> (a [I)
	at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
	- None

"RMI Scheduler(0)" daemon prio=6 tid=0x000000000acec800 nid=0x88c waiting on condition [0x000000000c3ae000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000c1498070> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2082)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1090)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:807)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
	- None

"RMI TCP Connection(1)-192.168.0.100" daemon prio=6 tid=0x000000000aceb000 nid=0xf84 runnable [0x000000000c2ae000]
   java.lang.Thread.State: RUNNABLE
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.read(SocketInputStream.java:152)
	at java.net.SocketInputStream.read(SocketInputStream.java:122)
	at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
	at java.io.BufferedInputStream.read(BufferedInputStream.java:254)
	- locked <0x00000000c1494348> (a java.io.BufferedInputStream)
	at java.io.FilterInputStream.read(FilterInputStream.java:83)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:549)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:828)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.access$400(TCPTransport.java:619)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$1.run(TCPTransport.java:684)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$1.run(TCPTransport.java:681)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:681)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
	- <0x00000000c1494508> (a java.util.concurrent.ThreadPoolExecutor$Worker)

"RMI TCP Accept-0" daemon prio=6 tid=0x000000000ad06800 nid=0x2780 runnable [0x000000000c0af000]
   java.lang.Thread.State: RUNNABLE
	at java.net.DualStackPlainSocketImpl.accept0(Native Method)
	at java.net.DualStackPlainSocketImpl.socketAccept(DualStackPlainSocketImpl.java:131)
	at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:398)
	at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:199)
	- locked <0x00000000c14922c8> (a java.net.SocksSocketImpl)
	at java.net.ServerSocket.implAccept(ServerSocket.java:530)
	at java.net.ServerSocket.accept(ServerSocket.java:498)
	at sun.management.jmxremote.LocalRMIServerSocketFactory$1.accept(LocalRMIServerSocketFactory.java:52)
	at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:399)
	at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(TCPTransport.java:371)
	at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
	- None

"pool-1-thread-5" prio=6 tid=0x000000000aa6c800 nid=0x26e8 in Object.wait() [0x000000000b3af000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:503)
	at com.ali.review.PrintDataThread.run(PrintDataThread.java:33)
	- locked <0x00000000c142c0f0> (a java.util.concurrent.atomic.AtomicInteger)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
	- <0x00000000c14236a8> (a java.util.concurrent.ThreadPoolExecutor$Worker)

"pool-1-thread-4" prio=6 tid=0x000000000aa69800 nid=0x1240 in Object.wait() [0x000000000b2af000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:503)
	at com.ali.review.PrintDataThread.run(PrintDataThread.java:33)
	- locked <0x00000000c142c0f0> (a java.util.concurrent.atomic.AtomicInteger)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
	- <0x00000000c14237d8> (a java.util.concurrent.ThreadPoolExecutor$Worker)

"pool-1-thread-3" prio=6 tid=0x000000000aa13000 nid=0x2008 waiting for monitor entry [0x000000000b1af000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:503)
	at com.ali.review.PrintDataThread.run(PrintDataThread.java:33)
	- locked <0x00000000c142c0f0> (a java.util.concurrent.atomic.AtomicInteger)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
	- <0x00000000c1423578> (a java.util.concurrent.ThreadPoolExecutor$Worker)

"pool-1-thread-2" prio=6 tid=0x000000000aa12000 nid=0xfe0 in Object.wait() [0x000000000b0ae000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:503)
	at com.ali.review.PrintDataThread.run(PrintDataThread.java:33)
	- locked <0x00000000c142c0f0> (a java.util.concurrent.atomic.AtomicInteger)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
	- <0x00000000c1423448> (a java.util.concurrent.ThreadPoolExecutor$Worker)

"pool-1-thread-1" prio=6 tid=0x000000000a98c800 nid=0x1b50 in Object.wait() [0x000000000afaf000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:503)
	at com.ali.review.PrintDataThread.run(PrintDataThread.java:33)
	- locked <0x00000000c142c0f0> (a java.util.concurrent.atomic.AtomicInteger)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
	- <0x00000000c1423318> (a java.util.concurrent.ThreadPoolExecutor$Worker)

"Monitor Ctrl-Break" daemon prio=6 tid=0x000000000a997000 nid=0xcc0 runnable [0x000000000ae3e000]
   java.lang.Thread.State: RUNNABLE
	at java.net.DualStackPlainSocketImpl.accept0(Native Method)
	at java.net.DualStackPlainSocketImpl.socketAccept(DualStackPlainSocketImpl.java:131)
	at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:398)
	at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:199)
	- locked <0x00000000c1423a68> (a java.net.SocksSocketImpl)
	at java.net.ServerSocket.implAccept(ServerSocket.java:530)
	at java.net.ServerSocket.accept(ServerSocket.java:498)
	at com.intellij.rt.execution.application.AppMain$1.run(AppMain.java:90)
	at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
	- None

"Service Thread" daemon prio=6 tid=0x0000000008fb7000 nid=0x1f40 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"C2 CompilerThread1" daemon prio=10 tid=0x0000000008fb1000 nid=0x348 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"C2 CompilerThread0" daemon prio=10 tid=0x0000000008faf000 nid=0x2108 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"Attach Listener" daemon prio=10 tid=0x0000000008fae800 nid=0x2350 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"Signal Dispatcher" daemon prio=10 tid=0x0000000008fab800 nid=0x2234 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"Finalizer" daemon prio=8 tid=0x0000000008f5f800 nid=0xfac in Object.wait() [0x000000000a30f000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
	- locked <0x00000000c1408f20> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
	at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

   Locked ownable synchronizers:
	- None

"Reference Handler" daemon prio=10 tid=0x0000000008f56800 nid=0x1d14 in Object.wait() [0x000000000a20e000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:503)
	at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
	- locked <0x00000000c1408920> (a java.lang.ref.Reference$Lock)

   Locked ownable synchronizers:
	- None

"main" prio=6 tid=0x00000000030d0800 nid=0x2578 waiting on condition [0x00000000030ce000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
	at java.lang.Thread.sleep(Native Method)
	at com.ali.review.PrintDataMain.main(PrintDataMain.java:27)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

   Locked ownable synchronizers:
	- None

"VM Thread" prio=10 tid=0x0000000008f52800 nid=0x11c4 runnable 

"GC task thread#0 (ParallelGC)" prio=6 tid=0x00000000030e7800 nid=0x2374 runnable 

"GC task thread#1 (ParallelGC)" prio=6 tid=0x00000000030e9000 nid=0x1980 runnable 

"GC task thread#2 (ParallelGC)" prio=6 tid=0x00000000030eb000 nid=0x242c runnable 

"GC task thread#3 (ParallelGC)" prio=6 tid=0x00000000030ec800 nid=0xd04 runnable 

"VM Periodic Task Thread" prio=10 tid=0x0000000008fda000 nid=0x2774 waiting on condition 

JNI global references: 165

线程dump信息中可以看到:RUNNABLE、TIMED_WAITING (on object monitor)、BLOCKED、WAITING (线程创建和终止状态不在dump中体现)

对dump信息我们尤其要注意:

     死锁,Deadlock(重点关注)
     执行中,Runnable  
     等待资源,Waiting on condition(重点关注)

     等待获取监视器,Waiting on monitor entry(重点关注)

"pool-1-thread-3" prio=6 tid=0x000000000aa13000 nid=0x2008 waiting for monitor entry [0x000000000b1af000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:503)
    at com.ali.review.PrintDataThread.run(PrintDataThread.java:33)
    - locked <0x00000000c142c0f0> (a java.util.concurrent.atomic.AtomicInteger)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
    - <0x00000000c1423578> (a java.util.concurrent.ThreadPoolExecutor$Worker)

进入waiting for monitor entry的原因是使用了 counter.wait()


     暂停,Suspended
     对象等待中,Object.wait() 或 TIMED_WAITING
     阻塞,Blocked(重点关注) 
     停止,Parked

转载于:https://my.oschina.net/zhaoxp/blog/979132

你可能感兴趣的:(线程dump详解)