【问题标题】:Why non-daemon thread is terminating if in jUnit test?如果在 jUnit 测试中,为什么非守护线程会终止?
【发布时间】:2012-11-25 12:17:00
【问题描述】:

以下 daemon-bean 正在运行:

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;
            }
        }

    }
}

它是守护进程,所以如果单例会终止。

所以,下面的非守护进程 bean 正在等待他:

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");

    }

}

bean 的 Spring 配置是:

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

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

问题是:为什么从 main 运行它可以工作,而如果从 jUnit 测试运行它却不工作?

运行代码是

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

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

在 main 的情况下,我看到所有的心跳。在 jUnit 的情况下,我只看到心跳 0,然后消息“等待开始”并且程序被终止,就好像没有人在这里等待非守护线程一样。

这可能是什么原因?

【问题讨论】:

    标签: java multithreading spring jvm daemon


    【解决方案1】:

    当您从 main 运行代码时,它会创建两个 bean,因此会创建两个线程 - 守护进程和非守护进程。只要非守护线程正在运行,您的应用程序就不会退出。所以它起作用了。

    从 JUnit 运行时不同。一旦 JUnit 测试方法完成(并且它在 Spring 上下文启动后立即完成),JUnit 就会假定您的测试已经完成。因此它会杀死你所有的线程,基本上是整个 JVM。

    记住你的Waitor1 bean 会产生一个 JUnit 不关心的后台线程。一旦你离开@Test,JUnit 方法就会停止一切。

    【讨论】:

    • 它只以某种特殊方式杀死我的线程,或者只是用System.exit() 终止JVM?
    • @SuzanCioc:这取决于您如何运行 JUnit 测试(IDE、surefire、CI 服务器),但基本上它会使用 System.exit() 杀死 JVM。
    • 能以某种方式避免这种情况吗?即,如果某些后台非守护线程仍在运行,就好像您希望测试失败。我更喜欢 JUnit 框架断言每个测试需要 不超过 说 1 分钟(或 2 小时),而不是突然蒸发所有内容。有“及时终止程序”这样的方面,这是程序正确的一部分。
    猜你喜欢
    • 2012-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多