java:如何设置全局线程ID?

java:如何设置全局线程ID?,java,multithreading,log4j,distributed,Java,Multithreading,Log4j,Distributed,是否有可能为线程设置唯一ID?在分布式系统中,线程是在许多不同的机器上创建的(例如,通过RMI) 我需要它来创建日志消息。从我的研究中,我知道它可以使用log4jmdc/ndc完成,但只能在单线程中完成。我的问题是在创建线程时必须设置ID(对不同JVM上的线程使用相同的ID,但对相同的请求使用相同的ID) 我是分布式系统的新手。如果您想拥有一个全局唯一的请求id,可以使用带有计数器的prcoessAndName(见下文),并将其与消息/请求一起传递,然后使用它设置线程名称 public void

是否有可能为线程设置唯一ID?在分布式系统中,线程是在许多不同的机器上创建的(例如,通过RMI)

我需要它来创建日志消息。从我的研究中,我知道它可以使用log4jmdc/ndc完成,但只能在单线程中完成。我的问题是在创建线程时必须设置ID(对不同JVM上的线程使用相同的ID,但对相同的请求使用相同的ID)


我是分布式系统的新手。

如果您想拥有一个全局唯一的请求id,可以使用带有计数器的prcoessAndName(见下文),并将其与消息/请求一起传递,然后使用它设置线程名称

public void processRequest(String uniqueRequestId, args) {
    Thread t = Thread.currrentThread();
    String tName = t.getName();
    try {
        t.setName("Processing " + uniqueRequestId);
        // preform process request
    } finally {
        t.setName(tName);
    }
}
这样,线程的名称将包含请求id,而不管它在哪个线程/机器中运行。如果您在日志中包括线程的名称,那么它将被包括在内


您可以使用

String processAndHost = ManagementFactory.getRuntimeMXBean().getName()
您可以在此附加描述性名称或计数器

这样,所有线程名称都将是唯一的

您可以假设此名称是全局唯一的,前提是,a)您有唯一的主机名b)进程未重新启动,因此经常会出现两个客户端(在不同时间)在同一主机上具有相同进程id的问题

这可以与本地唯一id结合,以获得分布式唯一id

ExecutorService service = Executors.newCachedThreadPool(new ThreadFactory() {
    final String processName = ManagementFactory.getRuntimeMXBean().getName();
    final AtomicLong counter = new AtomicLong();
    @Override
    public Thread newThread(Runnable r) {
        String name = processName+"-"+counter.getAndIncrement();
        return new Thread(r, name);
    }
});
for(int i=0;i<10;i++)
    service.submit(new Runnable() {
        @Override
        public void run() {
            System.out.println("["+Thread.currentThread().getName()+"] - Hello World.");
            Thread.yield();
        }
    });
service.shutdown();

您可以给线程一个名称(请参阅类
java.lang.Thread
的不同构造函数)。您可以为每个线程创建一个名称,该名称由计算机名和唯一的数字组成


如果您正在使用例如
ExecutorService
创建线程,那么您可以将该
ExecutorService
传递给您自己的
java.util.concurrent.ThreadFactory
实现,以生成线程并设置其名称。

您可以设置线程的名称,但不能设置/更改线程的ID 来自线程的getId方法的java文档

()


“返回此线程的标识符。线程ID是创建此线程时生成的正长数字。线程ID是唯一的,在其生存期内保持不变。当线程终止时,此线程ID可以重新使用。”

没有不可接受的线程创建开销

您应该通过请求ID或会话ID进行日志记录,而不是不可能实现甚至不存在的全局线程ID


我认为您需要对clicktrack日志进行一些研究。

这是否意味着我可以为threadA在不同的JVM上自动创建的threadB设置相同的名称?@trebuchet不,他没有说过这一点,甚至没有类似的意思。他没有回答你的实际问题,其他几个问题也没有。@EJP好的,我在理解上有一些困难。但这样设置ID是可能的吗?听起来很合理。但线程能识别是哪个请求创建了它吗?或者请求ID是否应该与控制流一致?如何做到这一点?一旦请求进入系统,您就将其填充到日志MDC中。请求完成后,将其从MDC中删除。那么你就不必去摆弄线程ID了。@A.H.听起来不错!但我不确定当请求通过很多线程时它是否可以工作。我认为MDC只能在一个请求=一个线程时提供帮助。但是如果我错了,这可能是一个很好的解决方案。如果请求真的是从一个线程传递到另一个线程,那么你真的有问题了。然后每个接收线程都必须执行MDC设置。这完全取决于您的框架——是否有一些中心位置可以节省地处理此类横切关注点——我们不知道。@EJP我已经开始了我的研究。但当我尝试在谷歌上搜索“clicktrack logging”时,我没有发现任何有用的东西。你知道一些例子或教程吗?@Perter Lawrey-我们能用这个唯一的名称跟踪从第一个线程到最后一个线程的请求吗?他不希望它们是全局唯一的,Peter,他希望它们在分布式请求中是全局的。“对不起,没有回答。”你真幸运。现在很难说孩子们的穿着方式:-)如果您自己编写RPC/消息传递库,可以将其添加为字段并自动使用。如果您试图使用标准RMI,您唯一的选择就是将其添加为对象中的字段或方法的参数。@PeterLawrey我使用RMI。我想,添加字段/参数是我需要的解决方案。
[9480@myhost-0] - Hello World.
[9480@myhost-3] - Hello World.
[9480@myhost-2] - Hello World.
[9480@myhost-1] - Hello World.
[9480@myhost-5] - Hello World.
[9480@myhost-4] - Hello World.
[9480@myhost-6] - Hello World.
[9480@myhost-7] - Hello World.
[9480@myhost-0] - Hello World.
[9480@myhost-7] - Hello World.