Java分布式键值存储中ReplicaPoller线程ID重复问题排查
多Server实例启动后ReplicaPoller线程ID重复的疑惑
我正在开发一个Java分布式键值存储程序,包含Server和ReplicaPoller两个实现Runnable接口的类。
Server类代码
public class Server implements Runnable { boolean createdPoller = false; // ... public void run() { // ... if (!createdPoller) { ReplicaPoller replicaPoller = new ReplicaPoller(); Thread replicaPollerThread = new Thread(replicaPoller); replicaPollerThread.start(); createdPoller = true; } // ... } }
ReplicaPoller类代码
public class ReplicaPoller implements Runnable { // ... public void run() { logger.info(hostServer.name + " " + Thread.currentThread().threadId()); // hostServer 是创建当前ReplicaPoller实例的Server // ... } }
问题现象
启动2个Server实例后,对应的ReplicaPoller日志显示相同的线程ID,但每个Server都创建了新的ReplicaPoller线程实例,找不到问题原因。
补充信息
- 外部配置服务通过
Runtime.getRuntime().exec执行以下命令启动多个Server实例:
其中java -jar server.jar -p port -n name-p指定监听端口,-n为服务器唯一标识。 - 使用log4j统一将日志输出到
server.log,日志内容示例:2023-03-21 13:21:33,447 INFO [Thread-2] 127.0.0.1:8029: 127.0.0.1:8029 252023-03-21 13:21:37,648 INFO [Thread-2] 127.0.0.1:8062: 127.0.0.1:8062 25 - 使用JDK19,
threadId()方法可正常运行,IDE提示getId()已废弃。
原因分析与解决办法
这是正常现象,线程ID仅在单个JVM进程内唯一,跨进程不具备唯一性。
你通过Runtime.getRuntime().exec启动的是两个独立的JVM进程,每个进程的线程ID分配完全独立,因此不同进程内的线程出现相同ID符合JVM设计逻辑。日志中的[Thread-2]是线程名称,同样仅为进程内标识,不同进程的线程可以拥有相同名称。
如果需要区分跨进程的线程,建议在日志中加入进程ID(PID),可通过ProcessHandle.current().pid()获取当前进程的PID,将其添加到日志内容中,即可明确区分不同进程下的线程。
内容的提问来源于stack exchange,提问作者PM25
相关产品推荐
相关产品推荐

