[英]Java how to get caller from separate thread?
嗯......不確定這是否可行,但如果你在一個單獨的線程上運行,怎么會在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" ?
}
}
用例是這樣的:我正在記錄大量數據,我根本不想阻止主線程。 一些日志記錄可能是快速和小數據,但有些可能會記錄轉儲很多東西。 問題還在於,現在,編寫代碼的方式,大約有600多個入口點進入callerMethod()
,因此重構將是一個相當大的挑戰。
或者:
如果你能證明Thread.currentThread().getStackTrace()[2].getMethodName();
保證是每次少於5毫秒的恆定時間操作,那么在主線程上可以接受。
編輯:
好的,您想要避免堆棧跟蹤。 我環顧了一下:確定調用者的復雜性實際上是在LogRecord
。 如果您可以通過Logger.setSourceClassName()
手動設置調用者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
將起作用,但我有點質疑你為什么要這樣做。 對於調試可能,但這是我能想到的唯一用例。 (PS我必須改變堆棧跟蹤中的偏移量。“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();
}
public class ThreadTest{
public static void main(String[] args) {
new Main().callerMethod();
}
}
class Main{
public void callerMethod() {
new Thread(new MyRunnable(new Throwable())).start();
}
class MyRunnable implements Runnable {
Throwable t;
MyRunnable(Throwable t) {
this.t = t;
}
@Override
public void run() {
StackTraceElement[] ses = t.getStackTrace();
System.out.println(ses[0].getClassName() + ":" + ses[0].getMethodName() );
}
}
}
有兩種情況。
Thread.
如果重寫Thread.start(),
可以在那里查看堆棧跟蹤。 Runnable.
在這種情況下,原則上你無法知道。 您可以知道的是Runnable,
通過在構造函數中查看堆棧跟蹤來創建Runnable,
但這不一定與啟動該線程的方法相同。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.