没有为Runnable调用@PreDestroy

时间:2015-07-11 16:59:55

标签: java multithreading spring annotations runnable

我有一个spring上下文,其中我们有Runnable bean这样开始:

public void startChildAndWait(Class type) {
  BaseMyDispatcher child = appContext.getBean(type);
  child.initialize(this); //The child references its parent during run method
  new Thread(child).start();
  synchronized(LOCK_OBJECT) {
    LOCK_OBJECT.wait(someTime);
  }
}

BaseMyDispatcher类是一个抽象类,SampleRunnableX是带有原型范围的实现,基类基本上有@PostConstruct方法和@PreDestroy方法(其主要功能是在LOCK_OBJECT上调用notify),当然一个Run方法

我的问题是调用了PostConstruct方法,但是当Run方法完成时,对象似乎没有被销毁,因此没有调用PreDestroy方法,并且我在LOCK_OBJECT上等待父进程卡住

代码在父Runnable内部的一个函数中调用(在ThreadPoolExecutor中执行,并使用相同的方法startChildAndWait以相同的方式启动(顺序)几个子项,每次都传递一个不同的类:

startChildAndWait(SampleRunnable1.class);
if(run2IsRequired && lastExitCode == 100) {//runIsRequired are booleans
  startChildAndWait(SampleRunnable2.class);
}
if(run3IsRequired && lastExitCode == 100) {//lastExitCode is an integer
  startChildAndWait(SampleRunnable3.class);
}

那么如何在完成子线程时调用PreDestroy方法呢?

3 个答案:

答案 0 :(得分:2)

来自the documentation

  

与其他作用域相比,Spring不管理原型bean的完整生命周期:容器实例化,配置和组装原型对象,并将其交给客户端,没有该原型实例的进一步记录。因此,尽管无论范围如何都在所有对象上调用初始化生命周期回调方法,但在原型的情况下,不会调用已配置的销毁生命周期回调。

如果您想在run()方法完成时发生某些事情,请将该代码放在run()方法的末尾。

答案 1 :(得分:0)

当应用程序关闭时,将调用

@PreDestroy回调方法,您需要向JVM注册一个关闭挂钩,并在JVM退出时关闭其中的应用程序上下文。

//Create applicationContext
final ApplicationContext appContext = 

//register ashutdown hook on application context
Runtime.getRuntime().addShutdownHook(new Thread() {
   public void run() {
       appContext.close();
   }});

如果你想在子线程完成时执行一些代码,最好把它放在run方法的末尾(线程本身)。

答案 2 :(得分:0)

遇到了这个问题,我使它能够在实现javax.ejb.Startup的{​​{1}}上添加EJB注释

Runnable

OR

@Startup @Singleton public class Task implements Runnable{ //... @PreDestroy public void stop(){ stop(); } } 上下文访问/触摸此Sigleton对象至少一次。