Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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,这里有一个不寻常的问题:是否有可能获得最初生成当前正在运行的线程的类/方法?运行堆栈跟踪将在当前线程的调用堆栈顶部自然停止。正常情况下,否 如果可以控制线程的创建,则可以将线程子类化并在构造函数中注册堆栈跟踪。当然,这就是创建线程的方法,而不一定是调用.start()的方法。因此,最好重写此方法 但是通常您会使用线程池,在这里您想知道哪个方法将任务提交给执行者的execute(),而不是哪个方法启动了线程。有可能与生成对象合作-它可以将信息写入线程对象(例如,如果你想要一种黑客方式,或者你可以为

这里有一个不寻常的问题:是否有可能获得最初生成当前正在运行的线程的类/方法?运行堆栈跟踪将在当前线程的调用堆栈顶部自然停止。

正常情况下,否

如果可以控制线程的创建,则可以将线程子类化并在构造函数中注册堆栈跟踪。当然,这就是创建线程的方法,而不一定是调用
.start()
的方法。因此,最好重写此方法


但是通常您会使用线程池,在这里您想知道哪个方法将任务提交给执行者的
execute()
,而不是哪个方法启动了线程。

有可能与生成对象合作-它可以将信息写入线程对象(例如,如果你想要一种黑客方式,或者你可以为此目的创建一个字段)你可以稍后用于调试等。但是我认为没有任何“内置”方式来获取此信息。

不,这是不可能的。实现这一点的方法可能是在
线程之前提供
建议。
开始()
使用AspectJ…当然,您可以子类
线程
,修补JDK代码(不同的启动类路径)等等,但AspectJ似乎是最可移植、最优雅的解决方案。

是的,您可以: 我提供两种方式:一种是标准方式,另一种是半黑客方式

大多数答案都太过火了,因为它应该是Java中的内置函数

安装安全管理器并重写
SecurityManager.getThreadGroup()
,您可以轻松获取堆栈跟踪,也可以通过重写其余的方法禁用其余的安全检查

Hacky one:在主线程中安装一个InheritableThreadLocal(名为main并由方法main(String[]args)运行的线程)。重写受保护的
InheritableThreadLocal.childValue(T parentValue)
即可

注意:您可以获得正在创建的线程和父线程(引用)的堆栈跟踪,但这应该足以跟踪问题

我决定写一个超级简单的示例来说明它是多么简单: 在这里你可以看到结果。看看这个例子,我想我在这个网站上发布过的最优雅的解决方案,大部分是b/c,它不明显,但简单而聪明

package bestsss.util;

import java.util.Arrays;

public class StackInterceptor extends InheritableThreadLocal<StackTraceElement[]>{
    public static final StackInterceptor instance;
    static{
        instance = new StackInterceptor();
        instance.set(new Throwable().getStackTrace());
    }

    @Override
    protected StackTraceElement[] childValue(StackTraceElement[] parentValue) {
        return new Throwable().getStackTrace();
    }

    //test//
    public static void main(String[] args) {
        Runnable r= new Runnable(){
            @Override
            public void run() {
                System.out.printf("%s - creation stack: %s%n", Thread.currentThread(), Arrays.toString(instance.get()).replace(',', '\n'));
            }           
        };

        Thread t1 = new Thread(r, "t1");
        //spacer
        Thread t2 = new Thread(r, "t2");
        t1.start();
        t2.start();     
    }
}
包bestsss.util;
导入java.util.array;
公共类StackInterceptor扩展了InheritableThreadLocal{
公共静态最终StackInterceptor实例;
静止的{
实例=新的StackInterceptor();
set(new Throwable().getStackTrace());
}
@凌驾
受保护的StackTraceElement[]子值(StackTraceElement[]父值){
返回新的Throwable().getStackTrace();
}
//试验//
公共静态void main(字符串[]args){
Runnable r=新的Runnable(){
@凌驾
公开募捐{
System.out.printf(“%s-创建堆栈:%s%n”,Thread.currentThread(),Arrays.toString(instance.get()).replace(“,”,“\n”);
}           
};
螺纹t1=新螺纹(r,“t1”);
//间隔棒
螺纹t2=新螺纹(r,“t2”);
t1.start();
t2.start();
}
}
线程[t1,5,main]-创建堆栈:[bestsss.util.StackInterceptor.childValue(StackInterceptor.java:13) bestsss.util.StackInterceptor.childValue(StackInterceptor.java:1) java.lang.ThreadLocal$ThreadLocalMap。(ThreadLocal.java:334) java.lang.ThreadLocal$ThreadLocalMap。(ThreadLocal.java:242) createInheritedMap(ThreadLocal.java:217) java.lang.Thread.init(Thread.java:362) java.lang.Thread.(Thread.java:488) main(StackInterceptor.java:25)] 线程[t2,5,main]-创建堆栈:[bestsss.util.StackInterceptor.childValue(StackInterceptor.java:13) bestsss.util.StackInterceptor.childValue(StackInterceptor.java:1) java.lang.ThreadLocal$ThreadLocalMap。(ThreadLocal.java:334) java.lang.ThreadLocal$ThreadLocalMap。(ThreadLocal.java:242) createInheritedMap(ThreadLocal.java:217) java.lang.Thread.init(Thread.java:362) java.lang.Thread.(Thread.java:488) main(StackInterceptor.java:27)]
祝你好运,黑客行为愉快。

我希望你这样做是为了进行一些黑客调试,而不是为了做任何重要的事情。哈哈,你的假设是正确的。自从我开始走这条路以来,我一直在忍着鼻子:-D相关(但不完全相同):@Mark,它可以用于安全原因,尽管我确信它不是。如果你控制池,没有什么好奇怪的,你甚至可以控制线程工厂,所以它就是线程工厂。@bestsss:是的。我的观点是,这个线程工厂方法通常不是你真正想知道的-你会想知道是谁(哪个方法)将工作提交到线程池(或者谁创建了可运行对象)。为此,线程池必须向所有任务添加元数据,并以某种方式提供检索此任务的方法。瞧,您有
newTaskFor(…)
AbstractExecutorService
中修饰任务。相反,知道第一个任务何时产生线程可能非常重要。虽然原因不明显,但新创建的线程从父线程继承了相当多的内容,需要勤勉的ThreadFactory来防止泄漏(ClassLoader、AccessControlContext、ThreadGroup等)使用
newTaskFor
…的好主意,但是使用默认线程池(ThreadPoolExecutor)不要在那里存储任何关于调用线程的元数据,是吗?我没有想到线程泄漏的影响,这是一个很好的观点。但我不认为有任何“内置”的方式来获取此信息,SecurityManager正是出于这个原因创建的,用于跟踪对潜在安全风险代码的调用。使用InheritableThreadLocal的解决方案是美丽的o Thread[t1,5,main] - creation stack: [bestsss.util.StackInterceptor.childValue(StackInterceptor.java:13) bestsss.util.StackInterceptor.childValue(StackInterceptor.java:1) java.lang.ThreadLocal$ThreadLocalMap.(ThreadLocal.java:334) java.lang.ThreadLocal$ThreadLocalMap.(ThreadLocal.java:242) java.lang.ThreadLocal.createInheritedMap(ThreadLocal.java:217) java.lang.Thread.init(Thread.java:362) java.lang.Thread.(Thread.java:488) bestsss.util.StackInterceptor.main(StackInterceptor.java:25)] Thread[t2,5,main] - creation stack: [bestsss.util.StackInterceptor.childValue(StackInterceptor.java:13) bestsss.util.StackInterceptor.childValue(StackInterceptor.java:1) java.lang.ThreadLocal$ThreadLocalMap.(ThreadLocal.java:334) java.lang.ThreadLocal$ThreadLocalMap.(ThreadLocal.java:242) java.lang.ThreadLocal.createInheritedMap(ThreadLocal.java:217) java.lang.Thread.init(Thread.java:362) java.lang.Thread.(Thread.java:488) bestsss.util.StackInterceptor.main(StackInterceptor.java:27)]