监控线程的3种方法

1. JDK命令行工具 - jstack

jps -l

查询当前运行线程

barry@Y430P:~/data/projects/test$ jps -l
18339 /usr/share/dbeaver//plugins/org.eclipse.equinox.launcher_1.4.0.v20161219-1356.jar
9046 org.jetbrains.jps.cmdline.Launcher
16087 com.intellij.idea.Main
9049 test.threadjava.ThreadGroupTest
9131 sun.tools.jps.Jps
27133 org.jetbrains.jps.cmdline.Launcher
6606 org.jetbrains.plugins.scala.nailgun.NailgunRunner

jstack -[operation] pid

其中operation:

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

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

-l:长期监听

barry@Y430P:~/data/projects/test$ jstack 9049
2019-01-02 16:33:25
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.171-b11 mixed mode):

"Attach Listener" #17 daemon prio=9 os_prio=0 tid=0x00007f03fc001000 nid=0x23e3 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"DestroyJavaVM" #16 prio=5 os_prio=0 tid=0x00007f044c00e000 nid=0x235c waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Thread 4" #15 prio=5 os_prio=0 tid=0x00007f044c4a0800 nid=0x2388 waiting on condition [0x00007f0411c36000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at test.threadjava.ThreadGroupTest.run(ThreadGroupTest.java:18)
        at java.lang.Thread.run(Thread.java:748)

"Thread 3" #14 prio=5 os_prio=0 tid=0x00007f044c49f000 nid=0x2387 waiting on condition [0x00007f0411d37000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at test.threadjava.ThreadGroupTest.run(ThreadGroupTest.java:18)
        at java.lang.Thread.run(Thread.java:748)

"Thread 2" #13 prio=5 os_prio=0 tid=0x00007f044c49d000 nid=0x2386 waiting on condition [0x00007f0411e38000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at test.threadjava.ThreadGroupTest.run(ThreadGroupTest.java:18)
        at java.lang.Thread.run(Thread.java:748)

"Thread 1" #12 prio=5 os_prio=0 tid=0x00007f044c49b800 nid=0x2385 waiting on condition [0x00007f0411f39000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at test.threadjava.ThreadGroupTest.run(ThreadGroupTest.java:18)
        at java.lang.Thread.run(Thread.java:748)

"Thread 0" #11 prio=5 os_prio=0 tid=0x00007f044c49a000 nid=0x2384 waiting on condition [0x00007f041203a000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at test.threadjava.ThreadGroupTest.run(ThreadGroupTest.java:18)
        at java.lang.Thread.run(Thread.java:748)

"Service Thread" #10 daemon prio=9 os_prio=0 tid=0x00007f044c476800 nid=0x2382 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread3" #9 daemon prio=9 os_prio=0 tid=0x00007f044c461800 nid=0x2381 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread2" #8 daemon prio=9 os_prio=0 tid=0x00007f044c45f800 nid=0x2380 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" #7 daemon prio=9 os_prio=0 tid=0x00007f044c45d000 nid=0x237f waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #6 daemon prio=9 os_prio=0 tid=0x00007f044c45b800 nid=0x237e waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Monitor Ctrl-Break" #5 daemon prio=5 os_prio=0 tid=0x00007f044c459800 nid=0x237d runnable [0x00007f0412958000]
   java.lang.Thread.State: RUNNABLE
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
        at java.net.SocketInputStream.read(SocketInputStream.java:171)
        at java.net.SocketInputStream.read(SocketInputStream.java:141)
        at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
        at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
        - locked <0x000000076d0bba70> (a java.io.InputStreamReader)
        at java.io.InputStreamReader.read(InputStreamReader.java:184)
        at java.io.BufferedReader.fill(BufferedReader.java:161)
        at java.io.BufferedReader.readLine(BufferedReader.java:324)
        - locked <0x000000076d0bba70> (a java.io.InputStreamReader)
        at java.io.BufferedReader.readLine(BufferedReader.java:389)
        at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)

"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f044c20a000 nid=0x237c runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f044c1d7800 nid=0x2374 in Object.wait() [0x00007f0412fee000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x000000076ce08ed0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
        - locked <0x000000076ce08ed0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:212)

"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007f044c1d2800 nid=0x2373 in Object.wait() [0x00007f04130ef000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x000000076ce06bf8> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
        - locked <0x000000076ce06bf8> (a java.lang.ref.Reference$Lock)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

"VM Thread" os_prio=0 tid=0x00007f044c1cb000 nid=0x2370 runnable 

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

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

jcmd -l 

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

barry@Y430P:~/data/projects/test$ jcmd -l
18339 /usr/share/dbeaver//plugins/org.eclipse.equinox.launcher_1.4.0.v20161219-1356.jar -os linux -ws gtk -arch x86_64 -showsplash -launcher /usr/share/dbeaver/dbeaver -name Dbeaver --launcher.library /usr/share/dbeaver//plugins/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.1.551.v20171108-1834/eclipse_1630.so -startup /usr/share/dbeaver//plugins/org.eclipse.equinox.launcher_1.4.0.v20161219-1356.jar --launcher.overrideVmargs -exitdata 17800b -vm /usr/bin/java -vmargs -XX:+IgnoreUnrecognizedVMOptions -Xms64m -Xmx1024m -jar /usr/share/dbeaver//plugins/org.eclipse.equinox.launcher_1.4.0.v20161219-1356.jar
9493 sun.tools.jcmd.JCmd -l
9046 org.jetbrains.jps.cmdline.Launcher /home/barry/app/idea2018/lib/guava-21.0.jar:/home/barry/app/idea2018/lib/resources_en.jar:/home/barry/app/idea2018/lib/commons-codec-1.9.jar:/home/barry/app/idea2018/lib/nanoxml-2.2.3.jar:/home/barry/app/idea2018/lib/protobuf-java-3.0.0.jar:/home/barry/app/idea2018/lib/lz4-java-1.3.jar:/home/barry/app/idea2018/lib/idea_rt.jar:/home/barry/app/idea2018/lib/jna.jar:/home/barry/app/idea2018/lib/asm-all.jar:/home/barry/app/idea2018/lib/httpclient-4.5.2.jar:/home/barry/app/idea2018/lib/netty-all-4.1.13.Final.jar:/home/barry/app/idea2018/lib/util.jar:/home/barry/app/idea2018/lib/jgoodies-forms.jar:/home/barry/app/idea2018/lib/commons-logging-1.2.jar:/home/barry/app/idea2018/lib/javac2.jar:/home/barry/app/idea2018/lib/aether-1.1.0-all.jar:/home/barry/app/idea2018/lib/snappy-in-java-0.5.1.jar:/home/barry/app/idea2018/lib/oro-2.0.8.jar:/home/barry/app/idea2018/lib/jna-platform.jar:/home/barry/app/idea2018/lib/httpcore-4.4.5.jar:/home/barry/app/idea2018/lib/log4j.jar:/home/barry/app/id
16087 com.intellij.idea.Main
9049 test.threadjava.ThreadGroupTest
27133 org.jetbrains.jps.cmdline.Launcher /home/barry/app/idea2018/lib/guava-21.0.jar:/home/barry/app/idea2018/lib/resources_en.jar:/home/barry/app/idea2018/lib/commons-codec-1.9.jar:/home/barry/app/idea2018/lib/nanoxml-2.2.3.jar:/home/barry/app/idea2018/lib/protobuf-java-3.0.0.jar:/home/barry/app/idea2018/lib/lz4-java-1.3.jar:/home/barry/app/idea2018/lib/idea_rt.jar:/home/barry/app/idea2018/lib/jna.jar:/home/barry/app/idea2018/lib/asm-all.jar:/home/barry/app/idea2018/lib/httpclient-4.5.2.jar:/home/barry/app/idea2018/lib/netty-all-4.1.13.Final.jar:/home/barry/app/idea2018/lib/util.jar:/home/barry/app/idea2018/lib/jgoodies-forms.jar:/home/barry/app/idea2018/lib/commons-logging-1.2.jar:/home/barry/app/idea2018/lib/javac2.jar:/home/barry/app/idea2018/lib/aether-1.1.0-all.jar:/home/barry/app/idea2018/lib/snappy-in-java-0.5.1.jar:/home/barry/app/idea2018/lib/oro-2.0.8.jar:/home/barry/app/idea2018/lib/jna-platform.jar:/home/barry/app/idea2018/lib/httpcore-4.4.5.jar:/home/barry/app/idea2018/lib/log4j.jar:/home/barry/app/id
6606 org.jetbrains.plugins.scala.nailgun.NailgunRunner 3200 4c70a862-3824-4418-8bb8-4097c167783d

jcmd 13 help 

查询jcmd所有帮助文档

barry@Y430P:~/data/projects/test$ jcmd 9049 help
9049:
The following commands are available:
JFR.stop
JFR.start
JFR.dump
JFR.check
VM.native_memory
VM.check_commercial_features
VM.unlock_commercial_features
ManagementAgent.stop
ManagementAgent.start_local
ManagementAgent.start
GC.rotate_log
Thread.print
GC.class_stats
GC.class_histogram
GC.heap_dump
GC.run_finalization
GC.run
VM.uptime
VM.flags
VM.system_properties
VM.command_line
VM.version
help

For more information about a specific command use 'help <command>'.

jcmd 13 help Thread.print

查询Thread.print的帮助文档

barry@Y430P:~/data/projects/test$ jcmd 9049 help Thread.print
9049:
Thread.print
Print all threads with stacktraces.

Impact: Medium: Depends on the number of threads.

Permission: java.lang.management.ManagementPermission(monitor)

Syntax : Thread.print [options]

Options: (options must be specified using the <key> or <key>=<value> syntax)
        -l : [optional] print java.util.concurrent locks (BOOLEAN, false)

jcmd 13 Thread.print

执行线程13的命令监控

barry@Y430P:~/data/projects/test$ jcmd 9049 Thread.print
9049:
2019-01-02 16:41:00
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.171-b11 mixed mode):

"Attach Listener" #17 daemon prio=9 os_prio=0 tid=0x00007f03fc001000 nid=0x23e3 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"DestroyJavaVM" #16 prio=5 os_prio=0 tid=0x00007f044c00e000 nid=0x235c waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Thread 4" #15 prio=5 os_prio=0 tid=0x00007f044c4a0800 nid=0x2388 waiting on condition [0x00007f0411c36000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at test.threadjava.ThreadGroupTest.run(ThreadGroupTest.java:18)
        at java.lang.Thread.run(Thread.java:748)

"Thread 3" #14 prio=5 os_prio=0 tid=0x00007f044c49f000 nid=0x2387 waiting on condition [0x00007f0411d37000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at test.threadjava.ThreadGroupTest.run(ThreadGroupTest.java:18)
        at java.lang.Thread.run(Thread.java:748)

"Thread 2" #13 prio=5 os_prio=0 tid=0x00007f044c49d000 nid=0x2386 waiting on condition [0x00007f0411e38000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at test.threadjava.ThreadGroupTest.run(ThreadGroupTest.java:18)
        at java.lang.Thread.run(Thread.java:748)

"Thread 1" #12 prio=5 os_prio=0 tid=0x00007f044c49b800 nid=0x2385 waiting on condition [0x00007f0411f39000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at test.threadjava.ThreadGroupTest.run(ThreadGroupTest.java:18)
        at java.lang.Thread.run(Thread.java:748)

"Thread 0" #11 prio=5 os_prio=0 tid=0x00007f044c49a000 nid=0x2384 waiting on condition [0x00007f041203a000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at test.threadjava.ThreadGroupTest.run(ThreadGroupTest.java:18)
        at java.lang.Thread.run(Thread.java:748)

"Service Thread" #10 daemon prio=9 os_prio=0 tid=0x00007f044c476800 nid=0x2382 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread3" #9 daemon prio=9 os_prio=0 tid=0x00007f044c461800 nid=0x2381 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread2" #8 daemon prio=9 os_prio=0 tid=0x00007f044c45f800 nid=0x2380 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" #7 daemon prio=9 os_prio=0 tid=0x00007f044c45d000 nid=0x237f waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #6 daemon prio=9 os_prio=0 tid=0x00007f044c45b800 nid=0x237e waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Monitor Ctrl-Break" #5 daemon prio=5 os_prio=0 tid=0x00007f044c459800 nid=0x237d runnable [0x00007f0412958000]
   java.lang.Thread.State: RUNNABLE
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
        at java.net.SocketInputStream.read(SocketInputStream.java:171)
        at java.net.SocketInputStream.read(SocketInputStream.java:141)
        at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
        at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
        - locked <0x000000076d0bba70> (a java.io.InputStreamReader)
        at java.io.InputStreamReader.read(InputStreamReader.java:184)
        at java.io.BufferedReader.fill(BufferedReader.java:161)
        at java.io.BufferedReader.readLine(BufferedReader.java:324)
        - locked <0x000000076d0bba70> (a java.io.InputStreamReader)
        at java.io.BufferedReader.readLine(BufferedReader.java:389)
        at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)

"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f044c20a000 nid=0x237c runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

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)

  

注意:第三种方式只适合监控单线程的情况,不适合监控子线程,如有子线程,请不要使用此种方式。有兴趣的可以试下如果监控子线程的情况会出现什么情况?

原文地址:https://www.cnblogs.com/barrywxx/p/10184435.html