Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何找到父线程的名称?_Java_Multithreading - Fatal编程技术网

Java 如何找到父线程的名称?

Java 如何找到父线程的名称?,java,multithreading,Java,Multithreading,我知道,当我们谈论过程时,我们可以有“父母”和“孩子”。但是有可能获取父线程名吗 我做了研究,但我只找到了答案 编辑:我尝试设置名称: public class Main { public static void main(String[] args) { Thread r = new ThreadA(); r.start(); } } public class ThreadA extends Thread { public v

我知道,当我们谈论过程时,我们可以有“父母”和“孩子”。但是有可能获取父线程名吗

我做了研究,但我只找到了答案


编辑:我尝试设置名称:

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());
    }
}

否-Java或.NET中都没有“父”线程的特定概念。但是,根据您引用的.NET答案,如果您自己创建线程,则始终可以在新线程的名称中指定一个名称,指示“创建者”线程名称

编辑:示例代码在开始之前设置名称。。。但在它启动后会覆盖它,忽略以前的名称

我期望的是:

String currentName = Thread.currentThread.name();
Thread thread = new Thread(new RunnableC());
thread.setName("C (started by" + currentName + ")");
thread.start();
这将是设置线程名称的唯一位置

注意,这也使用了实现
Runnable
的思想,而不是扩展
Thread
。这是一个单独的问题,但在大多数情况下是首选方法

我知道,当我们谈论过程时,我们可以有“父母”和“孩子”。但是有可能获取父线程名称吗

线程没有对父线程的引用,因此无法从特定线程获取父线程的名称。在查看代码时,父线程用于获取守护进程状态、优先级和其他信息,但名称不存储在新的
thread
对象中

您提到,您需要有线程的名称,以便可以对那些“一起在控制流中”的线程进行分组。我会查看
ThreadGroup
s。它们不会经常使用,但在这种情况下,您可能希望:

ThreadGroup threadGroup = new ThreadGroup("mythreadgroup");
Thread thread = new Thread(threadGroup, new Runnable() {...});
...
// then you can do such methods as
threadGroup.enumerate(...);
使用线程组,可以将多个线程连接在一起。当然,你自己也可以通过收藏来完成这项工作


编辑:

您提到,真正的问题是如何衡量分布式系统的每个组件(在本例中是RMI处理程序)中的“花费时间”

恐怕这里没有简单的答案。对于挂钟,您必须将每个RMI方法调用开始时的
System.currentTimeMillis()
与结束时的时间进行比较。您还可以使用以下代码测试线程使用的CPU时间

ThreadInfo threadInfo =
    ManagementFactory.getThreadMXBean().getThreadCpuTime(thread.getId()); 
要获取“用户”时间,请使用
getThreadUserTime(…)
。我不确定线程ID是否被重用,所以可能您需要做的就是在集合中记录RMI调用中的所有线程ID,然后在监视线程中记录它们的CPU和用户时间

我怀疑RMI线程有一个特定的名称,因此您的监视线程可以在线程列表中找到执行此操作的线程,但您无法确定哪个线程正在处理哪个RMI请求


最后,要考虑的是在过程中的多个点上使用时间戳,并在调用之间传递这个<代码>长[] /代码>。这会增加一小部分的数据开销,但这样您就可以对分布式系统的各个不同部分的性能有一个良好的感觉。

在接受的答案中,Gray提到线程局部变量可能是从启动另一个线程的线程继承的(即父母对子女;请注意,术语“父母”和“子女”在此没有任何特殊的技术含义)

基于这一想法,似乎有一种方法可以通过以下方式来确定父线程:在父线程中设置的任何值(如
名称
)都将自动在子线程中可用


此外,如果我们不控制子线程(例如,我们在线程中运行一个第三方组件,它会产生一些线程,我们希望跟踪这些线程),那么也可以使用这种机制


例如,这可能允许我们拍摄所有正在运行的线程的快照,并找出哪些线程是由我们的线程启动的,以及这些线程的子线程,等等。所有这些线程的子线程都应该可以很好地用于监视目的。不确定它是否对其他任何事情都有好处。

使用
InheritableThreadLocal
和仔细的crafted

@Override protected T childValue(T parentValue) {
    // Use Thread.currentThread() -- the parent -- to make a return value.
}
使您无法控制的线程能够将对自身的引用传递给它们创建的任何子线程——这将是它们的子线程与父线程最接近的事情

正如格雷所提到的,保留这样的引用可能会妨碍GC,因此有必要将它们包装在
WeakReference

下面是一个例子,每个线程都知道它的完整祖先,除非祖先已经死亡并被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();
        });
    }

}

我不确定这通常有多有用,但它可以用于,例如,按层次显示多个线程中的每个线程(您无法控制)的内容已打印到
System.out
或使用
java.util.Logger
登录;例如,这是您希望作为并行测试运行的测试框架的一部分实现的内容。

您是指包含
线程的
ThreadGroup
的名称吗?您可能需要解释为什么需要此信息。Yo您可能会发现有更好的解决方案。@Gray我需要为控制流中的线程使用相同的名称。听起来像是一个解决方案,谢谢!对于由RMI或在不同JVM上创建的线程,是否可以使用
ThreadGroup
?当然,在不同JVM上不可用。我认为您也无法控制RMI线程。它们是由JVM自动处理的。我仍然看不出为什么@trebuchet有必要这样做?听起来你好像是在圆孔中尝试方钉。我不知道“圆孔中的方钉”(非母语人士)是什么意思,但听起来很可怕:)我需要的是从每个请求中收集线程。我的任务是测量(对于每个请求)分布式系统中每个组件花费的时间,这是您应该问的问题。“我该如何衡量在R中花费的时间
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.