Java如何从单独的线程中获取调用者?

标签 java multithreading

嗯...不确定这是否可能,但是如果您在单独的线程上运行,如何在 Java 中获取真正调用者的类名(最好还有方法名)?我想将类名提取卸载到一个单独的线程(以免在我每秒执行 100 多个日志记录操作时阻塞 UI 线程)。

例如:

class Main {
    public void callerMethod() {
        Thread.currentThread().getStackTrace()[2].getMethodName(); // This gets me the caller. However, this is expensive to do on the UI Thread 100+ times per second. a call here can take up 70ms

        new Thread(new Runnable() {
            @Override
            public void run() {
                new SecondObject().iWantToKnowMyCaller();
            }
        }).start();
    }
}



class SecondObject {
    public void iWantToKnowMyCaller() {
        // how do i get the caller method here so that it's "callerMethod" from "Main" ?
    }
}

用例是这样的:我正在记录大量数据,我根本不想阻塞主线程。一些日志记录可能是快速且小的数据,但有些日志记录可能会转储很多东西。现在的问题还在于,按照代码的编写方式,callerMethod() 中有大约 600 多个入口点,因此重构将是一个相当大的挑战。

或者:

如果您可以证明 Thread.currentThread().getStackTrace()[2].getMethodName(); 每次都保证是一个小于 5 毫秒的恒定时间操作,那么在主线程上是可以接受的。

最佳答案

编辑:

好的,你想避免堆栈跟踪。我环顾四周:确定调用者的复杂性实际上在 LogRecord 中。如果您可以通过 Logger.setSourceClassName() 手动设置调用者(任何字符串),那么 LogRecord 将不再构建堆栈跟踪来查找调用者的姓名。

public class ThreadTest
{
   public static void main( String[] args )
   {
      LogRecord lr = new LogRecord( Level.INFO, "Hi" );
      lr.setSourceClassName( "ThreadTest.main" );  // anything, including null
      Logger.getAnonymousLogger().log( lr );
   }
}

原答案:

子类化 Thread 会起作用,但我有点疑问您为什么要这样做。也许用于调试,但这是我能想到的唯一用例。 (附:我不得不更改堆栈跟踪中的偏移量。“2”将获得 callerMethod 的调用方——在下面的示例中为“main”。)

public class ThreadTest
{
   public static void main( String[] args )
   {
      new Main().callerMethod();
   }
}

class Main {
    public void callerMethod() {
        final String callee = Thread.currentThread().getStackTrace()[1].getMethodName(); // This gets me the caller
        new MyThread(new Runnable() {
            @Override
            public void run() {
                new SecondObject().iWantToKnowMyCaller();
            }
        }){
        @Override
        public String getInvoker() { return callee; }}.start();
    }
}

abstract class MyThread extends Thread implements Invoker {    
   public MyThread( Runnable r )
   {
      super( r );
   }
}

class SecondObject {
    public void iWantToKnowMyCaller() {
        // how do i get the caller method here so that it's "callerMethod" from "Main" ?
       System.out.println( ((MyThread)(Thread.currentThread())).getInvoker() );
    }
}

interface Invoker {
   String getInvoker();
}

关于Java如何从单独的线程中获取调用者?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25736346/

相关文章:

python - 将 GDB 附加到 linux 中的垂死进程

node.js - 网络 worker 线程 : is it OK to use "require" inside worker?

java - 定义 long 或 double 变量时 volatile 关键字如何影响原子性

c++ - 确定景观中所有点与具有特定属性的点的距离的最快方法

java - 您正在探索通过 HTTP 而不是 HTTPS 描述或提供的 API

java - 运行自定义平方根函数时出错 (Java)

java - 事务管理器未回滚

c++ - 如何将 boost.lambda 与 boost.thread 结合使用来获取线程的返回值?

java - 将 GraphStream 图表添加到我的自定义 jPanel 中

java - 带有 MyBatis TypeHandler 的空对象模式