如何使用 aspectj 跟踪 Java 父线程 ID?
How to track Java parent thread id using aspectj?
我正在尝试跟踪以获取在使用 AspectJ 的程序中创建的每个新线程的父线程 ID。由于新线程使用 start() 方法开始执行,我认为以下技术应该有效:
aspect getParentThread {
pointcut threadStarting(): call(public void start());
Object around(): threadStarting() {
long parentThread = Thread.currentThread().getId();
Object ret = proceed();
long newThread = Thread.currentThread().getId();
if (parentThread != newThread) {
/*Store parentThread id in data structure */
}
return ret;
}
}
但这根本行不通。虽然建议执行了,但即使在 proceed() 完成之后也只有一个线程 ID。那么我在这里弄错了什么?
问题是你所有的代码都在父线程中执行,包括子线程启动后的代码,因为start()
方法是在父线程中调用并在父线程中执行的。
您可以尝试从调用 start()
方法的 Thread
对象获取新线程的 ID。
Warren Dew 是对的,但我想添加一些示例代码以展示如何使用 AspectJ 轻松完成此操作。您甚至不需要 around()
建议,一个简单的 before()
就足够了。
驱动申请:
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
new Thread(
new Runnable() {
@Override
public void run() {}
},
"first thread"
).start();
new Thread(
new Runnable() {
@Override
public void run() {}
},
"second thread"
).start();
}
}
看点:
package de.scrum_master.aspect;
public aspect ThreadStartInterceptor {
before(Thread childThread) :
call(public void Thread+.start()) &&
target(childThread)
{
System.out.printf(
"%s%n Parent thread: %3d -> %s%n Child thread: %3d -> %s%n",
thisJoinPoint,
Thread.currentThread().getId(),
Thread.currentThread().getName(),
childThread.getId(),
childThread.getName()
);
}
}
- 如您所见,我将方法拦截限制为
Thread+
,即 Thread
和子类实例。我正在明确地这样做,即使这不是绝对必要的,因为下一点已经隐式地做了:
- 我还将子线程绑定到一个可以在方面内巧妙使用的变量。
控制台日志:
call(void java.lang.Thread.start())
Parent thread: 1 -> main
Child thread: 11 -> first thread
call(void java.lang.Thread.start())
Parent thread: 1 -> main
Child thread: 12 -> second thread
我正在尝试跟踪以获取在使用 AspectJ 的程序中创建的每个新线程的父线程 ID。由于新线程使用 start() 方法开始执行,我认为以下技术应该有效:
aspect getParentThread {
pointcut threadStarting(): call(public void start());
Object around(): threadStarting() {
long parentThread = Thread.currentThread().getId();
Object ret = proceed();
long newThread = Thread.currentThread().getId();
if (parentThread != newThread) {
/*Store parentThread id in data structure */
}
return ret;
}
}
但这根本行不通。虽然建议执行了,但即使在 proceed() 完成之后也只有一个线程 ID。那么我在这里弄错了什么?
问题是你所有的代码都在父线程中执行,包括子线程启动后的代码,因为start()
方法是在父线程中调用并在父线程中执行的。
您可以尝试从调用 start()
方法的 Thread
对象获取新线程的 ID。
Warren Dew 是对的,但我想添加一些示例代码以展示如何使用 AspectJ 轻松完成此操作。您甚至不需要 around()
建议,一个简单的 before()
就足够了。
驱动申请:
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
new Thread(
new Runnable() {
@Override
public void run() {}
},
"first thread"
).start();
new Thread(
new Runnable() {
@Override
public void run() {}
},
"second thread"
).start();
}
}
看点:
package de.scrum_master.aspect;
public aspect ThreadStartInterceptor {
before(Thread childThread) :
call(public void Thread+.start()) &&
target(childThread)
{
System.out.printf(
"%s%n Parent thread: %3d -> %s%n Child thread: %3d -> %s%n",
thisJoinPoint,
Thread.currentThread().getId(),
Thread.currentThread().getName(),
childThread.getId(),
childThread.getName()
);
}
}
- 如您所见,我将方法拦截限制为
Thread+
,即Thread
和子类实例。我正在明确地这样做,即使这不是绝对必要的,因为下一点已经隐式地做了: - 我还将子线程绑定到一个可以在方面内巧妙使用的变量。
控制台日志:
call(void java.lang.Thread.start())
Parent thread: 1 -> main
Child thread: 11 -> first thread
call(void java.lang.Thread.start())
Parent thread: 1 -> main
Child thread: 12 -> second thread