如何在 Java 中使用 AspectJ 记录父子线程 ID

How can I log Thread Id of Parent & Child using AspectJ in Java

我是 AspectJ 的新手。能够创建一个简单的 JUnit 和 Aspect 类 来记录 ThreadId,它记录父线程 ID。但是我不知道如何记录子 ThreadId。

给定以下代码片段,我想使用 AspectJ 记录父子线程的线程 ID。

JUnit:

@Test
public void testExecutorService() {
    ExecutorService service = Executors.newSingleThreadExecutor();
    Runnable task = new Runnable() {
        @Override
        public void run() {
            System.out.println("working on the task");
        }
    };
    service.submit(task);
}

方面:以下方面记录父 ThreadId。

before() :
    call(* ExecutorService+.submit(..))
 {
    System.out.println("Parent Thread Id: "+Thread.currentThread().getId());
    //System.out.println("Child Thread Id: "+??); //?? - how to capture child thread id?
 }

我知道它在这里使用了“之前”建议,并且它还在拦截提交方法,这也可能是一个问题。 如何使用正确的切入点表达式记录子线程 ID 和父线程 ID?

你可以做的是拦截提交的任务参数并增强该任务以打印你想要的内容:

Object around(Runnable task) : call(* ExecutorService+.submit(Runnable, ..)) && args( task)
{
    final long parentID = Thread.currentThread().getId();
    Runnable newTask =  () -> {
            System.out.println("Parent Thread Id: "+ parentID);
            System.out.println("Child Thread Id: "+Thread.currentThread().getId()); //?? - how to capture child thread id?
            task.run();
    };
    return proceed(newTask);
}

一旦异步任务被执行,执行它的线程的 id 就会被打印出来。

一个运行例子:

Main.java:

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

Test.java:

public class Test {
    public void testExecutorService() {
        ExecutorService service = Executors.newSingleThreadExecutor();
        service.submit(() ->  System.out.println("working on the task"));
        try {
            service.awaitTermination(2, TimeUnit.SECONDS);
            service.shutdown();
        }catch (InterruptedException ie) {
            Thread.currentThread().interrupt();
        }
    }
}

Example.aj

public aspect Example {
     
     Object around(Runnable task) : call(public Future<?> java.util.concurrent.ExecutorService+.submit(Runnable)) 
                        && args(task)
     {
         final long parentID = Thread.currentThread().getId();
         Runnable newTask =  () -> {
                 System.out.println("Parent Thread Id: "+ parentID);
                 System.out.println("Child Thread Id: "+Thread.currentThread().getId()); 
                 task.run();
         };
         return proceed(newTask);
     }
}