Java中线程执行完毕后为何日志线程号持续递增?
关于线程编号递增与线程终止的验证分析
咱们先拆解你的问题:你发现每次创建的oneClass线程,日志里的线程编号一直在递增,担心这些线程没有正常终止,但按Java线程的运行机制,线程会在run()方法执行完毕或抛出未捕获异常时自动终止。结合你的代码和日志,我来帮你理清情况:
1. 线程编号递增是正常现象,不代表线程未终止
Java虚拟机给线程分配的ID是全局唯一且递增的,一旦某个线程的ID被分配,即使该线程终止,这个ID也不会被回收复用。下次新建线程时,JVM会直接使用下一个更大的数字作为线程ID。所以你看到的Thread-92、Thread-93这种编号递增,完全是正常的JVM行为,和线程是否存活没有直接关系。
2. 从日志看,你的线程已经正常终止
你的控制台日志里,每个线程(比如Thread-92、Thread-93)都输出了thread finish,这说明oneClass的run()方法已经完整执行完毕——线程会在run()方法的最后一行代码执行完成后,自动进入TERMINATED状态,也就是终止状态。
3. 如何手动验证线程是否真的终止?
如果你还是想确认,这里有几个简单的验证方法:
- 在代码中打印线程状态:在
oneClass的run()方法最后添加一行日志,打印当前线程的状态:
线程终止前的状态会是logger.info("Thread " + Thread.currentThread().getId() + " is terminating, state: " + Thread.currentThread().getState());TERMINATED(当run()执行完后,线程就会进入这个状态)。 - 用JDK工具查看存活线程:
- 用
jps命令找到你的Java进程ID; - 执行
jstack <你的进程ID>,查看输出的线程列表——如果那些Thread-xx不在列表里,说明它们已经终止了。
- 用
- 给线程设置自定义名称:在
oneClass的构造函数里给线程设置一个辨识度高的名字,方便排查:
之后用public oneClass(){ Thread my_thread = new Thread(this, "OneClass-Worker-" + System.currentTimeMillis()); my_thread.start(); }jstack查看时,就能很容易找到这些线程是否还存活。
4. 代码优化建议(避免潜在资源泄漏)
你的oneClass的run()方法里,Socket和流的关闭逻辑可以优化,建议使用try-with-resources语法,确保资源在异常情况下也能被正确关闭;另外注意你原代码中close变量未定义,需要补上:
public class oneClass implements Runnable { private static Logger logger = LogManager.getLogger(oneClass.class); private String host = "localhost"; private Integer port = 9999; private boolean close; // 补上未定义的变量 public oneClass(){ Thread my_thread = new Thread(this); my_thread.start(); } public void run() { // try-with-resources会自动关闭实现AutoCloseable的资源 try (Socket socket = new Socket(host, port); DataOutputStream out = new DataOutputStream(socket.getOutputStream())) { String msg = "Hi"; out.writeBytes(msg); logger.info("thread finish, thread ID: " + Thread.currentThread().getId()); } catch (IOException e) { logger.error("Thread encountered error", e); // 用日志打印异常,替代printStackTrace } } public boolean isClose() { return close; } public void setClose(boolean close) { this.close = close; } }
内容的提问来源于stack exchange,提问作者majo vlas
相关产品推荐
相关产品推荐

