The following daemon-bean is running:
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;
}
}
}
}
It is daemon, so would terminate if singleton.
So, the following non-daemon bean is waiting for him:
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");
}
}
The Spring configuration for beans is:
<bean id="daemon" class="beans.DaemonBean"/>
<bean id="waitor" class="beans.Waitor1">
<property name="joinable" ref="daemon"/>
</bean>
The question is: why is it working if runned from main and not working if ran from jUnit test?
Running code is
public static void main(String[] args) {
new ClassPathXmlApplicationContext("/beans/Waiting1.xml");
}
or
@Test
public void testWaiting1() {
new ClassPathXmlApplicationContext("/beans/Waiting1.xml");
}
In case of main I see all hearbeats. In case of jUnit I see only heartbeat 0, then message "Waiting started" and the program is terminated as if nobody waiting for non-daemon threads here.
What can be the reason of it?
Why JVM terminates the daemon thread if there is no user thread? The sole purpose of the daemon thread is that it provides services to user thread for background supporting task. If there is no user thread, why should JVM keep running this thread. That is why JVM terminates the daemon thread if there is no user thread.
Daemon threads are low priority threads which always run in background and user threads are high priority threads which always run in foreground. User Thread or Non-Daemon are designed to do specific or complex task where as daemon threads are used to perform supporting tasks.
Properties of Java Daemon ThreadJVM terminates itself when all user threads finish their execution. If JVM finds a running daemon thread, it terminates the thread and, after that, shutdown it. JVM does not care whether the Daemon thread is running or not. It is an utmost low priority thread.
Daemon threads are used for background supporting tasks and are only needed while normal threads are executing. If normal threads are not running and remaining threads are daemon threads then the interpreter exits. When a new thread is created it inherits the daemon status of its parent.
When you run your code from main
it creates both beans, thus two threads - daemon and non-daemon. As long as non-daemon thread is running, your application won't exit. So it works.
It's different when run from JUnit. As soon as JUnit test method completes (and it completes immediately after the Spring context is up), JUnit assumes your tests are done. Thus it kills all your threads and basically the whole JVM.
Remember your Waitor1
bean spawns a background thread which JUnit doesn't care about. As soon as you leave @Test
method JUnit will just stop everything.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With