2012-11-25 36 views
2

以下守護豆運行:爲什麼non-daemon線程在jUnit測試中終止?

public class DaemonBean extends Thread { 

    private final static Logger log = LoggerFactory.getLogger(DaemonBean.class); 

    { 
     setDaemon(true); 
     start(); 
    } 

    @Override 
    public void run() { 

     for(int i=0; i<10 && !isInterrupted(); ++i) { 
      log.info("Hearbeat {}", i); 
      try { 
       sleep(1000); 
      } catch (InterruptedException e) { 
       return; 
      } 
     } 

    } 
} 

它是守護進程,所以如果單將終止。

因此,下面的非守護豆正在等待他:

public class Waitor1 extends Thread { 

    private final static Logger log = LoggerFactory.getLogger(Waitor1.class); 

    private Thread joinable; 

    { 
     setDaemon(false); 
     setUncaughtExceptionHandler(new UncaughtExceptionHandler() { 

      @Override 
      public void uncaughtException(Thread t, Throwable e) { 
       log.error("Error in thread", e); 
      } 
     }); 
    } 

    public Thread getJoinable() { 
     return joinable; 
    } 

    public void setJoinable(Thread value) { 
     this.joinable = value; 
     if(this.joinable != null) { 
      start(); 
     } 
    } 

    @Override 
    public void run() { 

     log.info("Waiting started"); 

     try { 
      joinable.join(); 
     } catch (InterruptedException e) { 
      log.info("Thread interrupted"); 
      return; 
     } 

     log.info("Waiting ended"); 

    } 

} 

豆類Spring的配置文件是:

<bean id="daemon" class="beans.DaemonBean"/> 

    <bean id="waitor" class="beans.Waitor1"> 
     <property name="joinable" ref="daemon"/> 
    </bean> 

的問題是:爲什麼會工作,如果從主拼命地跑如果從jUnit測試運行,不工作?

運行的代碼是

public static void main(String[] args) { 
     new ClassPathXmlApplicationContext("/beans/Waiting1.xml"); 
    } 

@Test 
    public void testWaiting1() { 
     new ClassPathXmlApplicationContext("/beans/Waiting1.xml"); 
    } 

在主我看到所有hearbeats情況。在jUnit的情況下,我只看到心跳0,然後顯示消息「Waiting started」,程序終止,就好像沒有人在這裏等待非守護線程一樣。

可能是什麼原因呢?

回答

5

當您從main運行代碼時,它將創建兩個bean,即兩個線程 - 守護進程和非守護進程。只要非守護線程正在運行,您的應用程序將不會退出。所以它工作。

從JUnit運行時不同。只要JUnit測試方法完成(並且在Spring上下文啓動後立即完成),JUnit會假定您的測試已完成。因此它殺死了所有的線程,基本上是整個JVM。

記住你的Waitor1 bean產生一個JUnit不關心的後臺線程。只要你離開@Test方法JUnit將停止一切。

+0

它以某種特殊方式殺死我的線程,或者只是用'System.exit()'終止JVM? –

+1

@SuzanCioc:它取決於你如何運行你的JUnit測試(IDE,surefire,CI服務器),但基本上它用'System.exit()'殺死JVM。 –