监控线程的3种方法

Posted barrywxx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了监控线程的3种方法相关的知识,希望对你有一定的参考价值。

1. JDK命令行工具 - jstack

jps -l 查询当前运行线程

jstack -[operation] pid

其中operation:

-F:当 jstack pid没有响应时,使用-F强制dump线程信息

-m:打印java线程栈和本地线程栈

-l:长期监听,

打印锁信息 jstack -l 13 >/tmp/deadlock.txt -l 会打印锁的附加信息。

2.JDK1.7以后的命令行工具-jcmd

在JDK1.7后新增的一个命令行工具jcmd,它是一个多功能工具,可以用它来导出堆,查看Java进程,导出线程信息,执行GC等。

jcmd -l 

列出当前系统中的所有Java虚拟机

jcmd 13 help 

查询jcmd所有帮助文档

jcmd 13 help Thread.print

查询Thread.print的帮助文档

jcmd 13 Thread.print

执行线程13的命令监控

3. 通过程序监控

Java版本实现:

 1 import java.util.ArrayList;
 2 import java.util.List;
 3 
 4 /**
 5  * 类功能描述:
 6  *
 7  * @author WangXueXing create at 18-12-26 下午2:28
 8  * @version 1.0.0
 9  */
10 public class ThreadMonitor extends Thread {
11     private Logger LOGGER = LoggerFactory.getLogger(this.getClass());
12     private volatile boolean finished = false;
13     private Thread currentThread;
14     public ThreadMonitor(Thread currentThread){
15         this.currentThread = currentThread;
16     }
17 
18     @Override
19     public void run() {
20         while (!this.finished) {
21             StackTraceElement[] stackElements = this.currentThread.getStackTrace();
22             List<String> list = new ArrayList<>();
23             for(StackTraceElement stackElement : stackElements){
24                 list.add(stackElement.toString()+"
");
25             }
26             LOGGER.info(list.toString());
27 
28             try {
29                 Thread.sleep(1000);
30             } catch (InterruptedException e) {
31                 e.printStackTrace();
32             }
33         }
34     }
35 
36     public void setFinished(boolean finished) {
37         this.finished = finished;
38     }
39 
40     public void doSomething(){
41         List<Integer> list = new ArrayList<>();
42         for(int i=0; i<=100000000; i++){
43             list.add(i);
44         }
45     }
46 
47     public static void main(String[] args){
48         Thread currentThread = Thread.currentThread();
49         ThreadMonitor tm = new ThreadMonitor(currentThread);
50         tm.start();
51         tm.doSomething();
52         tm.setFinished(true);
53     }
54 }

Scala版本实现,Scala还是强大些,比Java更加灵活,可以传入代码块:

 1 import org.slf4j.LoggerFactory
 2 
 3 /**
 4   * 类功能描述:线程监控器
 5   *
 6   * @author WangXueXing create at 18-12-25 下午3:44
 7   * @version 1.0.0
 8   */
 9 object ThreadMonitor {
10   val LOGGER = LoggerFactory.getLogger(getClass)
11   /**
12     * 线程监控器
13     * 注意,当代码块里有子线程,可能无法监控到对应线程日志
14     * @param currentThread 当前执行线程
15     * @param intervalTime 打印线程堆栈的间隔时间, 单位为毫秒;选传,默认为1秒
16     * @param codeBlock 要监控的代码块
17     * @tparam T
18     */
19   def threadMonitor[T](currentThread: Thread, intervalTime: Option[Long]=None) (codeBlock: => T) {
20     //set the real real interval time as 1s if the param intervalTime is None
21     val realIntervalTime = intervalTime match {
22       case Some(x) => x
23       case None =>  1000
24     }
25     @volatile
26     var flag = false
27     val t = new Thread(() => {
28         while (!flag) {
29           val stackElements = currentThread.getStackTrace
30           LOGGER.info(stackElements.map(_.toString).mkString("
"))
31           Thread.sleep(realIntervalTime)
32         }
33       })
34     t.start()
35     try{
36       codeBlock
37     } finally {
38       flag = true
39     }
40   }
41 }

调用监控线程:

import test.thread.ThreadMonitor

/**
  * 类功能描述://TODO
  *
  * @author WangXueXing create at 18-12-27 下午1:18
  * @version 1.0.0
  */
object Test {

  def doSomething(): Unit ={
    Range.apply(1, 100000000).map(_);
  }

  def main(args: Array[String]): Unit = {
    val currentThread = Thread.currentThread()
    ThreadMonitor.threadMonitor(currentThread){
      Test.doSomething();
    }
  }
}

  

运行输出结果如下:

13:23:07.955 [Thread-0] INFO  test.thread.ThreadMonitor$ - sun.net.www.protocol.file.Handler.parseURL(Handler.java:67)
java.net.URL.<init>(URL.java:622)
java.net.URL.<init>(URL.java:490)
sun.misc.URLClassPath$FileLoader.getResource(URLClassPath.java:1260)
sun.misc.URLClassPath.getResource(URLClassPath.java:239)
java.net.URLClassLoader$1.run(URLClassLoader.java:365)
java.net.URLClassLoader$1.run(URLClassLoader.java:362)
java.security.AccessController.doPrivileged(Native Method)
java.net.URLClassLoader.findClass(URLClassLoader.java:361)
java.lang.ClassLoader.loadClass(ClassLoader.java:424)
sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
java.lang.ClassLoader.loadClass(ClassLoader.java:357)
test.Test$.doSomething(Test.scala:14)
test.Test$.$anonfun$main$1(Test.scala:20)
test.Test$$$Lambda$1/33524623.apply$mcV$sp(Unknown Source)
scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
test.thread.ThreadMonitor$.threadMonitor(ThreadMonitor.scala:38)
test.Test$.main(Test.scala:20)
test.Test.main(Test.scala)
13:23:10.999 [Thread-0] INFO  test.thread.ThreadMonitor$ - scala.collection.immutable.Range.foreach(Range.scala:154)
scala.collection.TraversableLike.map(TraversableLike.scala:233)
scala.collection.TraversableLike.map$(TraversableLike.scala:226)
scala.collection.AbstractTraversable.map(Traversable.scala:104)
test.Test$.doSomething(Test.scala:14)
test.Test$.$anonfun$main$1(Test.scala:20)
test.Test$$$Lambda$1/33524623.apply$mcV$sp(Unknown Source)
scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
test.thread.ThreadMonitor$.threadMonitor(ThreadMonitor.scala:38)
test.Test$.main(Test.scala:20)
test.Test.main(Test.scala)
13:23:14.129 [Thread-0] INFO  test.thread.ThreadMonitor$ - scala.collection.immutable.Range.foreach(Range.scala:154)
scala.collection.TraversableLike.map(TraversableLike.scala:233)
scala.collection.TraversableLike.map$(TraversableLike.scala:226)
scala.collection.AbstractTraversable.map(Traversable.scala:104)
test.Test$.doSomething(Test.scala:14)
test.Test$.$anonfun$main$1(Test.scala:20)
test.Test$$$Lambda$1/33524623.apply$mcV$sp(Unknown Source)
scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
test.thread.ThreadMonitor$.threadMonitor(ThreadMonitor.scala:38)
test.Test$.main(Test.scala:20)
test.Test.main(Test.scala)
13:23:20.027 [Thread-0] INFO  test.thread.ThreadMonitor$ - scala.collection.immutable.Range.foreach(Range.scala:154)
scala.collection.TraversableLike.map(TraversableLike.scala:233)
scala.collection.TraversableLike.map$(TraversableLike.scala:226)
scala.collection.AbstractTraversable.map(Traversable.scala:104)
test.Test$.doSomething(Test.scala:14)
test.Test$.$anonfun$main$1(Test.scala:20)
test.Test$$$Lambda$1/33524623.apply$mcV$sp(Unknown Source)
scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
test.thread.ThreadMonitor$.threadMonitor(ThreadMonitor.scala:38)
test.Test$.main(Test.scala:20)
test.Test.main(Test.scala)
13:23:23.620 [Thread-0] INFO  test.thread.ThreadMonitor$ - scala.collection.immutable.Range.foreach(Range.scala:154)
scala.collection.TraversableLike.map(TraversableLike.scala:233)
scala.collection.TraversableLike.map$(TraversableLike.scala:226)
scala.collection.AbstractTraversable.map(Traversable.scala:104)
test.Test$.doSomething(Test.scala:14)
test.Test$.$anonfun$main$1(Test.scala:20)
test.Test$$$Lambda$1/33524623.apply$mcV$sp(Unknown Source)
scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
test.thread.ThreadMonitor$.threadMonitor(ThreadMonitor.scala:38)
test.Test$.main(Test.scala:20)
test.Test.main(Test.scala)

  

以上是关于监控线程的3种方法的主要内容,如果未能解决你的问题,请参考以下文章

多线程 Thread 线程同步 synchronized

RunLoop总结:RunLoop的应用场景

java 线程监控

活动到片段方法调用带有进度条的线程

性能测试三十二:监控之Java线程监控

稳定性 耗时 监控原因分析-- dubbo rpc 框架 的线程池,io 连接模型. 客户端,服务端