SpringBoot Web项目主线程去向疑问:启动后使用jcmd与hsdb均无法找到主线程
嘿,这个问题我太有共鸣了——当年刚上手Spring Boot Web项目的时候,我也对着jcmd $pid Thread.print的输出挠头:说好的主线程呢?怎么凭空消失了?其实真相是:主线程根本没消失,只是它的“身份”和状态变了,导致你容易忽略它。
我给你拆解一下整个过程:
1. 启动阶段:主线程是“大忙人”
当你执行java -jar your-app.jar启动项目时,JVM会立刻创建一个名为main的线程,它就是咱们说的主线程。接下来的所有启动逻辑——加载配置文件、初始化Spring上下文、创建和注入Bean、启动内嵌Web容器(Tomcat/Jetty/Undertow)——全都是这个main线程在扛。
2. 启动完成后:主线程变“看门大爷”
等内嵌Web容器启动完成,开始对外接收HTTP请求后,主线程并不会直接退出。它会钻进Web容器的await()方法里(比如Tomcat的StandardServer.await()),进入**WAITING(等待)**状态。
这个状态下,主线程啥也不干,就守着一个“关闭信号”——比如你按Ctrl+C发送SIGINT信号,或者用kill命令发送SIGTERM,或者代码里调用SpringApplication.exit()。只有收到这个信号,它才会唤醒,执行容器关闭、上下文销毁的逻辑,最后真正退出。
3. 为什么你找不到它?
原因一:线程列表里它藏在后面
jcmd $pid Thread.print的输出是按线程ID或状态排序的,WAITING状态的线程通常会排在RUNNABLE线程(比如Tomcat的工作线程)后面。你得耐心往下翻,找名称为main的线程,它的调用栈大概是这样的:
"main" #1 prio=5 os_prio=0 tid=0x00007f9e18009800 nid=0x2731 waiting on condition [0x00007f9e1f7ef000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x00000000d6020150> (a org.apache.catalina.core.StandardServer$Waiter) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at org.apache.catalina.core.StandardServer.await(StandardServer.java:460) at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start(TomcatWebServer.java:229) ... 后面是Spring Boot启动的调用栈
原因二:hsdb搜索方式不对
用hsdb工具时,别光盯着“RUNNABLE”状态的线程。切换到“Threads”标签,直接搜索线程名称main,就能找到它——它的调用栈肯定指向Web容器的await()方法,状态是WAITING。
总结
主线程从来没消失,只是从“启动应用的大忙人”变成了“守着应用关闭的看门大爷”。只要你仔细查看线程列表,找名称为main、状态为WAITING的线程,就能找到它的踪迹。
内容的提问来源于stack exchange,提问作者ght ggg

