是否有可能为线程设置唯一 ID?在分布式系统中,在许多不同的机器上创建线程(例如通过 RMI)?
我需要它来创建日志消息。根据我的研究,我知道可以使用 log4j mdc/ndc 来完成,但只能在单线程中完成。我的问题是必须在创建线程时设置 ID(为不同 JVM 上的线程使用相同的 ID,但用于相同的请求)
我是分布式系统的新手。
是否有可能为线程设置唯一 ID?在分布式系统中,在许多不同的机器上创建线程(例如通过 RMI)?
我需要它来创建日志消息。根据我的研究,我知道可以使用 log4j mdc/ndc 来完成,但只能在单线程中完成。我的问题是必须在创建线程时设置 ID(为不同 JVM 上的线程使用相同的 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();
印刷
[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.
您可以为线程命名(请参阅 class 的不同构造函数java.lang.Thread
)。您可以为每个线程组成一个名称,例如计算机名称加上一个唯一编号。
如果您正在使用例如创建线程ExecutorService
,那么您可以传递ExecutorService
您自己的实现java.util.concurrent.ThreadFactory
来创建线程并设置它们的名称。
并非没有不可接受的线程创建开销。
您应该通过请求 ID 或会话 ID 进行记录,而不是一些甚至不存在的无法实现的全局线程 ID。
我认为您需要对点击跟踪日志进行一些研究。
您可以为线程设置名称,但不能从 Thread 的 getId 方法的 java 文档中设置/更改线程的 ID
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#getId ()
“返回此线程的标识符。线程ID是创建此线程时生成的正长数。线程ID是唯一的,在其生命周期内保持不变。当一个线程终止时,该线程ID可能会被重用。”