如何使用aspectj跟踪Java父线程id?

时间:2015-08-30 15:20:22

标签: java multithreading aspectj aop

我正在尝试跟踪以获取使用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。那么我在这里出错了什么?

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

问题是所有代码都在父线程中执行,包括子线程启动后的代码,因为start()方法是从父线程中调用并执行的。

您可以尝试从调用Thread方法的start()对象获取新线程的ID。