You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 25
    
    2023-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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 04:45:08