【问题标题】:Thread creation listener线程创建监听器
【发布时间】:2012-09-11 13:11:19
【问题描述】:

是否可以在java中编写线程创建监听器?比如使用aop?!

我的意思是这样的,如果我的应用程序创建一个线程,我想在我自己的表、容器或其他东西中注册这个对象。

【问题讨论】:

  • 如果你在主线程中注册一个ClassLoader,希望它会被所有新线程继承,并且再次希望,任何线程都需要加载一些类,这意味着你的ClassLoader将被咨询,你有机会注册线程....
  • 我会沿着扩展Thread 的路径使用听众所需的方法。当然,仅适用于您的代码。
  • 您是否需要跟踪转换(例如:“现在已经创建了一个新线程,我必须立即对其做出反应”)还是拥有一个线程列表或一些线程就足够了在特定时间点在您的应用程序中/由您的应用程序创建(例如:“现在我想知道线程并用它们做一些事情。”)?
  • 我想编写自己的线程监视器,所以我需要立即“当前”线程对象。我将创建自己的装饰线程来处理所有这些监视内容 - 但问题是如何在不覆盖任何内容的情况下获取新线程将创建的信息 - “即时”。我想编写一个易于在任何应用程序中运行的监视器。
  • 查看编写 eclipse 调试器的人。也许他们可以给这个问题一个提示;)

标签: java multithreading jvm classloader


【解决方案1】:

我认为这可以通过 AOP(例如aspectj)实现。但是仍然需要创建自己的ThreadThreadGroup/Executor 类型,除非您可以使用切面编译器重新编译JDK 类。如果要在线程启动时注册,请在线程的 start 方法上定义切入点;如果要在创建线程对象时注册,请在池的 createThread 上定义切入点。


仅当您使用方面编译器重新编译 JDK 时,以下内容才有效: 所有线程都以Thread.start 开头,因此为该方法编写一个切入点,然后您可以使用建议来做您想做的事情。当然这并不完美,因为例如cachedThreadPool 执行程序可能不会为每个任务启动一个新线程,但也许如果您在Runnable.runCallable.call 而不是Thread.start 上注册一个切入点,那可能就足够了。

【讨论】:

  • 这可能适用于正在运行的线程,但问题是关于监听创建的线程而不是正在运行的线程。
  • @user454322 否。线程启动时将调用一个 before 通知。 (即调用这三种方法中的任何一种)
  • 我知道它会在线程启动之前调用,但是会在线程创建时调用?例如,如果线程创建但从未启动会发生什么?
  • @user454322。我明白了,我把这个问题解释为好像他想在“线程启动”事件上注册。我编辑了我的答案。
  • @zeller 听起来不错。那么在 Thread 类构造函数上注册切入点呢?它会起作用吗 - 像这样的东西?你怎么看?
【解决方案2】:

我会创建一个线程,不断列出 JVM 上所有正在运行的线程。
然后每次它注意到出现了一个新线程时,它都会以任何一种方式通知你代码中的一个类。

这里有一些关于如何列出当前在 JVM 上运行的所有线程的链接:

  1. Get a List of all Threads currently running in Java

  2. Listing All Running Threads

============

起始码:

ThreadCreationListener.java

public interface ThreadCreationListener {
    public void onThreadCreation(Thread newThread);
}

ThreadCreationMonitor.java

public class ThreadCreationMonitor extends Thread {
   private List<ThreadCreationListener> listeners;
   private boolean canGo;

   public ThreadCreationMonitor() {
      listeners = new Vector<ThreadCreationListener>();//Vector class is used because many threads may use a ThreadCreationMonitor instance.
      canGo = true;
      // Initialize the rest of the class here...
   }

   // Most important methods
   public void addListener(ThreadCreationListener tcl) {
        listeners.add(tcl);
   }

   public void removeListener(ThreadCreationListener tcl) {
        listeners.remove(tcl);
   }

   public void run() {
        List<Thread> runningThreads;
        List<Thread> lastRunningThreads;

        while(canGo) {
            // Step 1 - List all running threads (see previous links)
            // runningThreads = ...

            // Step 2 - Check for new threads and notify all listeners if necessary
            if (runningThreads.removeAll(lastRunningThreads)==true) {
                for(Thread t : runningThreads) {
                    for(ThreadCreationListener tcl : listeners) {
                        tcl.onThreadCreation(t);//Notify listener
                    }
                }
            }
        }
   }

   public void shutdown() {
       canGo = false;
   }

}

MyThreadInfoConsumer.java

public class MyThreadInfoConsumer implements ThreadCreationListener {
    public void onThreadCreation(Thread newThread) {
        // Process here the notification...
    }
}

Main.java

public class Main {
    public static void main(String[] args) {
       ThreadCreationMonitor tcm = new ThreadCreationMonitor();
       tcm.start();

       MyThreadInfoConsumer myTIC = new MyThreadInfoConsumer();
       tcm.addListener(myTIC);

       // rest of your code...
       // Don't forget to call tcm.shutdown() when exiting your application !
    }
}

【讨论】:

  • 这些例子很好用,但是没有监听器行为。我想知道 jvm 将创建新线程的信息让我们说'instatntly'而不覆盖任何东西。
  • @ŁukaszRzeszotarski 您可以从上面的示例中实现侦听器行为,但它们是关于运行线程而不是创建线程(如您所问)。
【解决方案3】:

也许你需要一个 ThreadGroup。所有线程都是 ThreadGroup 的成员,当您启动新线程时,默认情况下会将其添加到与其父级相同的组中。

理论上,当线程被添加或从组中删除时,它可能(但不推荐)子类得到通知。

可能轮询这个组的线程,或者轮询所有线程是更好的解决方案。

【讨论】:

  • 线程在创建时或启动时添加到线程组中?
  • 从代码中,它建议何时启动。如果你想知道一个线程是什么时候创建的,你需要对线程进行子类化(并更改所有线程创建代码)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多