ali*_*mon 8 java multithreading
我知道在谈论流程时我们可以拥有"父母"和"孩子".但是有可能得到父母的Thread
名字吗?
我做了我的研究,但我找到了仅针对.Net的答案
编辑:我尝试设置名称:
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());
}
}
Run Code Online (Sandbox Code Playgroud)
Gra*_*ray 10
我知道在谈论流程时我们可以拥有"父母"和"孩子".但是有可能获得父线程名称吗?
正如Jon所说,线程无法知道其父线程.这很重要,因为如果每个子节点都引用了分叉它们的线程,那么这将意味着内存中存在许多不必要的线程结构.GC无法回收父线程结构,或者如果孩子持有对它的引用,则重新使用父线程结构.
在查看代码时,父代用于获取守护程序状态,优先级和其他信息,但不存储在Thread
对象中.
您提到您需要拥有线程的名称,以便您可以对那些"在控制流中一起"的组进行分组.我会调查一下ThreadGroup
.它们不经常使用,但在这种情况下你可能想要:
ThreadGroup threadGroup = new ThreadGroup("mythreadgroup");
Thread thread = new Thread(threadGroup, new Runnable() {...});
...
// then you can do such methods as
threadGroup.enumerate(...);
Run Code Online (Sandbox Code Playgroud)
使用线程组,您可以将多个线程绑定在一起.当然,您也可以使用自己的系列来完成此操作.
编辑:
您提到真正的问题是如何衡量分布式系统的每个组件中的"花费的时间" - 在这种情况下是RMI处理程序.
我担心这里没有简单的答案.对于挂钟,您将不得不将System.currentTimeMillis()
每个RMI方法调用的开头与结束时的时间进行比较.您还可以使用以下代码来测试线程使用的CPU时间.
ThreadInfo threadInfo =
ManagementFactory.getThreadMXBean().getThreadCpuTime(thread.getId());
Run Code Online (Sandbox Code Playgroud)
获得您使用的"用户"时间getThreadUserTime(...)
.我不确定线程ID是否被重用,所以你可能需要做的就是记录集合中RMI调用中的所有线程ID,然后在监视线程中记录它们的CPU和用户时间.
我怀疑RMI线程有一个特定的名称,因此您的监视线程可以找到线程列表中的线程来执行此操作,但您无法确定哪个线程正在处理哪个RMI请求.
最后,要考虑的一件事是在过程中的多个点上采用时间戳,并在两次long[]
调用之间传递.这会增加一小部分数据开销,但您可以很好地了解分布式系统各个不同部分的性能.
不 - 在Java或.NET中没有"父"线程的特定概念.但是,根据您引用的.NET答案,如果您自己创建线程,则始终可以在新线程的名称中指定一个名称,以指示"创建者"线程名称.
编辑:您的示例代码在开始之前设置名称...但在启动后将其覆盖,忽略以前的名称.
我希望有类似的东西:
String currentName = Thread.currentThread.name();
Thread thread = new Thread(new RunnableC());
thread.setName("C (started by" + currentName + ")");
thread.start();
Run Code Online (Sandbox Code Playgroud)
这将是线程名称设置的唯一位置.
请注意,这也使用了实现Runnable
而不是扩展的想法Thread
.这是一个单独的问题,但在大多数情况下是首选方法.
使用InheritableThreadLocal<T>
精心制作
@Override protected T childValue(T parentValue) {
// Use Thread.currentThread() -- the parent -- to make a return value.
}
Run Code Online (Sandbox Code Playgroud)
使得你无法控制的线程可以将对自己的引用传递给它们创建的任何子线程 - 这将是他们的孩子与父母最接近的事情.
正如格雷所提到的那样,保留这样的引用可能会阻碍GC,因此将它们包装在一起WeakReference<Thread>
可能是必要的.
下面是一个示例,其中每个线程都知道它的完整祖先,除非祖先死亡并被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();
});
}
}
Run Code Online (Sandbox Code Playgroud)
此示例在我的机器上产生以下输出:
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.
Run Code Online (Sandbox Code Playgroud)
我不确定这是多么普遍有用,但它可以用来,例如,分层显示你打印System.out
或记录的多个线程(你无法控制的)中的每个线程java.util.Logger
; 例如,这是您希望作为具有并行测试运行的测试框架的一部分实现的.
归档时间: |
|
查看次数: |
17354 次 |
最近记录: |