监控线程的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()+"\n"); 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("\n")) 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)
注意:第三种方式只适合监控单线程的情况,不适合监控子线程,如有子线程,请不要使用此种方式。有兴趣的可以试下如果监控子线程的情况会出现什么情况?
每天一点成长,欢迎指正!