java 如何找到父线程的名称?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11722749/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to find the name of the parent thread?
提问by alicjasalamon
I know we can have 'parents' and 'children' when we are talking about processes. But is it possible to get parent Thread
name?
我知道当我们谈论流程时,我们可以有“父母”和“孩子”。但是有可能获得父母的Thread
名字吗?
I did my research, but I have found answer only for .Net
我做了我的研究,但我只找到了.Net 的答案
Edit: I tried setting names:
编辑:我尝试设置名称:
public class Main {
public static void main(String[] args) {
Thread r = new ThreadA();
r.start();
}
}
public class ThreadA extends Thread {
public void run() {
Thread.currentThread().setName("Thread A");
System.out.println("Here " + Thread.currentThread().getName());
Thread r = new ThreadB();
r.setName(Thread.currentThread().getName());
r.start();
}
}
public class ThreadB extends Thread {
public void run() {
Thread.currentThread().setName("Thread B");
System.out.println("Here " + Thread.currentThread().getName());
Thread r = new ThreadC();
r.setName(Thread.currentThread().getName());
r.start();
}
}
public class ThreadC extends Thread {
public void run() {
Thread.currentThread().setName("Thread C");
System.out.println("Here " + Thread.currentThread().getName());
}
}
回答by Jon Skeet
No - there's no particular concept of a "parent" thread in either Java or .NET. As per the .NET answer you referenced, however, if you're creating the thread yourself you can always give a name which indicates the "creator" thread name within the new thread's name.
不 - 在 Java 或 .NET 中没有“父”线程的特定概念。但是,根据您引用的 .NET 答案,如果您自己创建线程,则始终可以提供一个名称,该名称指示新线程名称中的“创建者”线程名称。
EDIT: Your sample code sets the name beforeit starts... but then overwrites it afterit starts, ignoring the previous name.
编辑:您的代码示例设置名称之前,它开始......但随后将其覆盖后,它开始,忽略以前的名称。
I'd expect something like:
我希望是这样的:
String currentName = Thread.currentThread.name();
Thread thread = new Thread(new RunnableC());
thread.setName("C (started by" + currentName + ")");
thread.start();
That would be the onlyplace the name of the thread would be set.
那将是唯一设置线程名称的地方。
Note that this also uses the idea of implementing Runnable
rather than extending Thread
. That's a separate matter, but is the preferred approach in most cases.
请注意,这也使用了实现Runnable
而不是扩展的想法Thread
。这是一个单独的问题,但在大多数情况下是首选方法。
回答by Gray
I know we can have 'parents' and 'children' when we are talking about processes. But is it possible to get parent Thread name?
我知道当我们谈论流程时,我们可以有“父母”和“孩子”。但是是否有可能获得父线程名称?
A thread does not have a reference to the parent thread so there is no way for you to get the name of the parent from a particular thread. In looking at the code, the parent thread is used to get daemon status, priority, and other information but the name is not stored in the new Thread
object.
线程没有对父线程的引用,因此您无法从特定线程获取父线程的名称。在查看代码时,父线程用于获取守护进程状态、优先级和其他信息,但名称未存储在新Thread
对象中。
You mentioned that you need to have the name of the threads so you can group those that "go together in a control flow". I would look into ThreadGroup
s. They aren't used too often but you might want to in this case:
您提到您需要拥有线程的名称,以便您可以将那些“在控制流中组合在一起”的线程分组。我会调查ThreadGroup
s。它们不经常使用,但在这种情况下您可能想要:
ThreadGroup threadGroup = new ThreadGroup("mythreadgroup");
Thread thread = new Thread(threadGroup, new Runnable() {...});
...
// then you can do such methods as
threadGroup.enumerate(...);
With thread-groups you can tie multiple threads together. You can, of course, do this with a collection as well yourself.
使用线程组,您可以将多个线程绑定在一起。当然,您也可以自己使用集合来执行此操作。
Edit:
编辑:
You mentioned that the realissue is how can you measure the "time spent" in each component of a distributed system – in this case the RMI handlers.
您提到真正的问题是如何衡量分布式系统的每个组件中的“时间花费”——在这种情况下是 RMI 处理程序。
I'm afraid there is no easy answer here. For wall clock, you are going to have to compare the System.currentTimeMillis()
at the start of each RMI method call with the time from the end. You can also use the following code to test the CPU time used by the thread.
恐怕这里没有简单的答案。对于挂钟,您必须将System.currentTimeMillis()
每个 RMI 方法调用开始时的时间与结束时的时间进行比较。您还可以使用以下代码来测试线程使用的 CPU 时间。
ThreadInfo threadInfo =
ManagementFactory.getThreadMXBean().getThreadCpuTime(thread.getId());
To get the "user" time you use getThreadUserTime(...)
. I'm not sure thread-ids are reused so maybe all you need to do is record all of the thread-ids in your RMI calls in a collection and then note their CPU and user times in a monitoring thread.
要获取“用户”时间,请使用getThreadUserTime(...)
. 我不确定线程 ID 是否被重用,所以也许您需要做的就是将 RMI 调用中的所有线程 ID 记录在一个集合中,然后在监视线程中记录它们的 CPU 和用户时间。
I suspect the RMI threads have a particular name so your monitoring thread could find the threads in the thread list to do this but you are not going to be able to determine which thread is handling which RMI request.
我怀疑 RMI 线程有一个特定的名称,因此您的监视线程可以在线程列表中找到线程来执行此操作,但您将无法确定哪个线程正在处理哪个 RMI 请求。
Lastly, one thing to consider is to take time stamps at a number of points in the process and to pass this long[]
around between calls. This would add some small percentage of data overhead but then you would be able to get a good feeling about the performance of the various different parts of your distributed system.
最后,要考虑的一件事是在过程中的多个点获取时间戳并long[]
在调用之间传递它。这会增加一小部分数据开销,但随后您将能够很好地了解分布式系统各个不同部分的性能。
回答by Jon Marius Venstad
Using InheritableThreadLocal<T>
with a carefully crafted
使用InheritableThreadLocal<T>
精心制作的
@Override protected T childValue(T parentValue) {
// Use Thread.currentThread() -- the parent -- to make a return value.
}
makes it possible for threads you have no control over to pass a reference to themselves to any child threads they create -- this will be the closest thing their children have to a parent.
使您无法控制的线程可以将对其自身的引用传递给它们创建的任何子线程——这将是它们的子线程与父线程最接近的事情。
As mentioned by Gray, keeping such references could hinder GC, so wrapping them in a WeakReference<Thread>
could be necessary.
正如 Gray 所提到的,保留此类引用可能会阻碍 GC,因此WeakReference<Thread>
可能需要将它们包装在 a 中。
Here is an example where each thread knows its full ancestry, unless ancestors are dead and buried by GC.
这是一个示例,其中每个线程都知道其完整的祖先,除非祖先已死并被 GC 掩埋。
import java.lang.ref.WeakReference;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;
import static java.lang.Thread.currentThread;
public class ThreadAncestry {
/** Linked list holding the thread which created the current one, and its ancestry */
static class Chain {
final Chain ancestors;
final WeakReference<Thread> parent;
Chain(Chain ancestors, Thread parent) {
this.ancestors = ancestors;
this.parent = new WeakReference<>(parent);
}
@Override
public String toString() {
Thread parent = this.parent.get();
return (parent == null ? "[dead and buried]" : parent.getName())
+ (ancestors == null ? "" : " -> " + ancestors);
}
}
/** Prints the current thread's ancestry, then spawns a new thread which does the same. */
static void spawnRecursively(InheritableThreadLocal<Chain> ancestors, int remainingSpawns) {
System.out.println( "The ancestors of " + currentThread().getName() + " are " + ancestors.get());
if (remainingSpawns > 0)
new Thread(() -> spawnRecursively(ancestors, remainingSpawns - 1)).start();
}
/** Uses an InheritableThreadLocal to record the ancestry of each thread as they are created. */
public static void main(String[] args) {
InheritableThreadLocal<Chain> ancestors = new InheritableThreadLocal<Chain>() {
@Override
protected Chain childValue(Chain parentValue) {
return new Chain(parentValue, currentThread()); // This is called by the parent thread.
}
};
spawnRecursively(ancestors, 3);
IntStream.range(0, 6).parallel().forEach(
i -> System.out.println( i + " ran on " + currentThread().getName()
+ " with ancestors " + ancestors.get()));
ExecutorService service = Executors.newSingleThreadExecutor();
service.submit(() -> {
System.out.println( currentThread().getName() + " has ancestors "
+ ancestors.get() + "; it will now attempt to kill these.");
System.gc(); // May not work on all systems.
System.out.println( currentThread().getName() + " now has ancestors "
+ ancestors.get() + " after attempting to force GC.");
service.shutdown();
});
}
}
This example results in the following output on my machine:
此示例在我的机器上产生以下输出:
The ancestors of main are null
The ancestors of Thread-0 are main
The ancestors of Thread-1 are Thread-0 -> main
The ancestors of Thread-2 are Thread-1 -> Thread-0 -> main
3 ran on main with ancestors null
4 ran on main with ancestors null
5 ran on ForkJoinPool.commonPool-worker-2 with ancestors main
0 ran on ForkJoinPool.commonPool-worker-3 with ancestors ForkJoinPool.commonPool-worker-1 -> main
1 ran on ForkJoinPool.commonPool-worker-1 with ancestors main
2 ran on ForkJoinPool.commonPool-worker-2 with ancestors main
pool-1-thread-1 has ancestors main; it will now attempt to kill these.
pool-1-thread-1 now has ancestors [dead and buried] after attempting to force GC.
I'm not sure how generally useful this is, but it can be used to, e.g., hierarchically display what each of a number of threads (over which you have no control) have printed to System.out
or logged with java.util.Logger
; this is something you would want to implement as part of a test framework with parallel test runs, for instance.
我不确定这有多大用处,但它可以用于,例如,分层显示多个线程(您无法控制)中的每一个打印System.out
或记录的内容java.util.Logger
;例如,这是您希望作为具有并行测试运行的测试框架的一部分来实现的。
回答by Evgeni Sergeev
In the accepted answer Gray mentions that the thread locals are possibly inherited from a thread that starts another thread (i.e. parent to child; note that the terms "parent" and "child" don't have any more special technical meaning here).
在接受的答案中,Gray 提到线程局部变量可能是从启动另一个线程的线程继承的(即父到子;请注意,术语“父”和“子”在这里没有任何特殊的技术含义)。
Based on that idea, it seems that there is a way to figure out the parent thread using InheritableThreadLocal: whatever value will be set in the parent (like name
) will be available in the child automatically.
基于这个想法,似乎有一种方法可以使用InheritableThreadLocal找出父线程:在父线程中设置的任何值(如name
)都将自动在子线程中可用。
Moreover, if we don't control the child threads (e.g. we run a third-party component in our thread, and it spawns a few threads, which we wish to keep track of), it might be possible to use this mechanism also. Reflection can let us see other threads' thread locals.
此外,如果我们不控制子线程(例如,我们在我们的线程中运行第三方组件,并且它产生了一些我们希望跟踪的线程),那么也可以使用这种机制。反射可以让我们看到其他线程的线程局部变量。
This might allow us to e.g. take a snapshot of all running threads, and figure out which ones were started by our thread, and children of those threads, etc. — all their descendants. Should work well for monitoring purposes. Not sure if it will be any good for anything else.
这可能允许我们例如拍摄所有正在运行的线程的快照,并找出哪些线程是由我们的线程启动的,以及这些线程的子线程等等——它们的所有后代。应该可以很好地用于监控目的。不确定它是否对其他任何东西都有好处。