Tuesday 2 June 2009

Daemon Thread in Java


  • Any thread created by main thread is by default user thread. Because when a new thread is created it inherits the daemon status of its parent. (Check output result)
  • Need to explicitly set daemon (setDaemon(true)) but this can only be called before starting thread otherwise it will throw IllegalThreadStateException if the related thread already started.  (Check output result) 
  • Normal thread and daemon threads differ in what happens when they exit. When the JVM halts any remaining daemon threads are abandoned: Finally blocks are not executed. Stacks are not unwound and JVM just exits. (Check output result)
  •  Main different is that as soon as all user thread finish execution java program or JVM terminates itself, JVM doesn't wait for daemon thread to finish there execution. As soon as last non daemon thread finished JVM terminates no matter how many Daemon thread exists or running inside JVM. (Check output result)


Sample Code

public class DaemonTest {

    public static void main(String[] args) {
        System.out.println("Entering main Method");
        WorkerThread wt = new WorkerThread();

        // When false, (i.e. when it's a user thread),
        // the Worker thread continues to run. finally block will run
        // When true, (i.e. when it's a daemon thread),
        // the Worker thread terminates when the main thread terminates. finally block doesn't run
        /** Set daemon flag */
        wt.setDaemon(true);
        wt.start();
        try {
            Thread.sleep(7500);
            System.out.println("Main Thread wake up");
        } catch (InterruptedException e) {
        }
        System.out.println("Main Thread ending");
    }

}

class WorkerThread extends Thread {

    public void run() {
        System.out.println("Entering WorkerThread run method IsDaemon:" + Thread.currentThread().isDaemon());
        try {
            System.out.println("In run Method: currentThread() is" + Thread.currentThread());
            int count = 0;
            while (count < 10) {
                System.out.println("Hello from Worker " + count++);
                try {
                    sleep(2000);
                } catch (InterruptedException e) {
                }
                System.out.println("In run method: woke up again");
            }
        } finally {
            System.out.println("NOTE : Leaving Worker run Method running finally block");
        }
    }
}


Output: User thread / Non-Daemon thread
Entering main Method
Entering WorkerThread run method IsDaemon:false
In run Method: currentThread() isThread[Thread-0,5,main]
Hello from Worker 0
In run method: woke up again
Hello from Worker 1
In run method: woke up again
Hello from Worker 2
In run method: woke up again
Hello from Worker 3
Main Thread wake up
Main Thread ending
In run method: woke up again
Hello from Worker 4
In run method: woke up again
Hello from Worker 5
In run method: woke up again
Hello from Worker 6
In run method: woke up again
Hello from Worker 7
In run method: woke up again
Hello from Worker 8
In run method: woke up again
Hello from Worker 9
In run method: woke up again
NOTE : Leaving Worker run Method running finally block

Process finished with exit code 0



Output: Daemon thread
Entering main Method
Entering WorkerThread run method IsDaemon:true
In run Method: currentThread() isThread[Thread-0,5,main]
Hello from Worker 0
In run method: woke up again
Hello from Worker 1
In run method: woke up again
Hello from Worker 2
In run method: woke up again
Hello from Worker 3
Main Thread wake up
Main Thread ending

Process finished with exit code 0



Output: Setting daemon flag after starting thread
Entering main Method
Exception in thread "main" java.lang.IllegalThreadStateException
 at java.lang.Thread.setDaemon(Thread.java:1275)
 at com.java.concurrency.c1.DaemonTest.main(DaemonTest.java:16)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Entering WorkerThread run method IsDaemon:false
In run Method: currentThread() isThread[Thread-0,5,main]
Hello from Worker 0
In run method: woke up again
Hello from Worker 1
In run method: woke up again
Hello from Worker 2
In run method: woke up again
Hello from Worker 3
In run method: woke up again
Hello from Worker 4
In run method: woke up again
Hello from Worker 5
In run method: woke up again
Hello from Worker 6
In run method: woke up again
Hello from Worker 7
In run method: woke up again
Hello from Worker 8
In run method: woke up again
Hello from Worker 9
In run method: woke up again
NOTE : Leaving Worker run Method running finally block

Process finished with exit code 1


NOTES:
Daemon thread which runs in background and mostly created by JVM for performing background tasks such as

  • Garbage collection
  • Performing asynchronous I/O task. ????
  • Listening for incoming connections ????
  • Collecting statistics and performing the status monitoring tasks
    • Sending and receiving network heartbeats , supplying the service monitoring tools
  • House keeping jobs