Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在线程终止时调用方法_Java_Multithreading - Fatal编程技术网

Java 在线程终止时调用方法

Java 在线程终止时调用方法,java,multithreading,Java,Multithreading,我正在编写一个java程序,它跟踪程序中创建的线程,然后在每个线程终止时执行一些工作 我在javadoc中没有看到任何“线程终止挂钩” 目前,我能想到的实现我的需求的唯一方法是保持线程对象并以重复的间隔查询其“状态” 有没有更好的办法 编辑: 我无法包装runnable或以任何方式修改runnable。 我的代码使用运行时插装,只检测创建的线程并获取对线程对象的引用。 runnable此时已在运行。您可以为runnable编写一个装饰程序,调用终止挂钩,并在创建线程时将线程代码包装在其中。您可以

我正在编写一个java程序,它跟踪程序中创建的线程,然后在每个线程终止时执行一些工作

我在javadoc中没有看到任何“线程终止挂钩”

目前,我能想到的实现我的需求的唯一方法是保持线程对象并以重复的间隔查询其“状态”

有没有更好的办法

编辑: 我无法包装runnable或以任何方式修改runnable。 我的代码使用运行时插装,只检测创建的线程并获取对线程对象的引用。
runnable此时已在运行。

您可以为runnable编写一个装饰程序,调用终止挂钩,并在创建线程时将线程代码包装在其中。

您可以使用

编辑


如果在线程未终止之前不能阻止主线程,则可以创建一个子主线程来调用线程,然后使用
join()
方法等待它们。

如果向每个run方法添加try/finally块,则在每个线程完成时将执行其中的代码。让线程负责自己的清理。

我看到了四种可能的方法

  • 将自己的线程子类与 重写的run()方法。添加 最后是螺纹块 终止
  • 将Runnable与 类似的装饰,也许作为一种装饰 包装所提供的产品 可运行的。一种变体是 子类Thread以应用 此包装器在构建时使用
  • 在上创建第二个要连接的线程() 真正的线程,从而检测其 终止
  • 如上所述,使用检测重写Thread.run()方法

  • 正如您所说,没有线程终止挂钩。你必须自己编写代码;在Runnables的run()方法的末尾调用控制器上的某个方法(AFAIK子类化线程被认为是不好的做法,您应该实现Runnable并创建一个以该Runnable为目标的线程)


    您还可以实现一个UncaughtExceptionHandler,以了解线程是否由于异常而异常终止,在这种情况下,您的控制器的方法将不会被调用。

    AspectJ可以帮助您在需要将代码注入第三方编译代码时实现这一点,但显然它在标准Java类库中不起作用

    看起来这里有一份关于这样做的白皮书,但不知道它是否实用。我想你得付钱


    您可以下载OpenJDK,自己安装钩子,编译一个自定义JRE并将其与应用程序一起发布:)

    如果您在java 1.5上运行,您可能可以使用java.lang.instrument和jvm的-javaagent选项来完成

    重新定义线程对象上的run方法,该对象应调用您的代码。您似乎已经在使用检测工具,所以它应该是可用的。当它修改运行时字节码时,您应该不会有问题

    也就是说,很难提供更具体、更详细的答案您的问题至少缺少jvm版本和正在使用的主要框架(想想spring aop、jboss aop、jvm版本等等)

    只需浏览一下
    java.lang.Thread
    sun.misc.VM
    的(sun 1.5)源代码,线程中有一个名为
    threadStatus
    的字段。它是一个
    private int
    ,其值映射到enum
    java.lang.Thread.State
    。我没有验证这一点,也没有确定它发生的速度,但当线程最终终止时,该值将设置为
    java.lang.thread.State.TERMINATED


    在这种相对简单的检测条件下,我认为在
    threadStatus
    上注入一个字段拦截器,当字段设置为特定的目标值时触发事件是相当简单的。

    这意味着我需要为我跟踪的每个线程“a”创建另一个线程“b”,以便“b”可以等待“a”加入。这似乎是最好的答案。除非你正在运行很多线程,否则这不重要——我已经运行了很多线程,在你达到数千个线程之前,不要太紧张。等待线程不会消耗CPU。无法修改可运行线程。编辑问题以澄清此问题。无法修改可运行的。编辑问题以澄清这一点。我认为装饰器背后的想法是,您不会修改Runnable,而是执行类似于将其包装到另一个对象中的操作。如果你说不能修改已经运行的线程,那就不同了。不能修改线程对象或可运行线程。使用join需要为我跟踪的每个线程增加一个线程