2

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

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

我是分布式系统的新手。

4

4 回答 4

2

如果您想拥有一个全局唯一的请求 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();

印刷

[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.
于 2012-07-26T07:56:23.493 回答
2

您可以为线程命名(请参阅 class 的不同构造函数java.lang.Thread)。您可以为每个线程组成一个名称,例如计算机名称加上一个唯一编号。

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

于 2012-07-26T07:56:45.197 回答
1

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

您应该通过请求 ID 或会话 ID 进行记录,而不是一些甚至不存在的无法实现的全局线程 ID。

我认为您需要对点击跟踪日志进行一些研究。

于 2012-07-26T08:19:46.710 回答
0

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

http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#getId ()

“返回此线程的标识符。线程ID是创建此线程时生成的正长数。线程ID是唯一的,在其生命周期内保持不变。当一个线程终止时,该线程ID可能会被重用。”

于 2012-07-26T07:58:43.787 回答