Daemon threads
A “daemon” thread is one that is supposed to provide a general service in the background as long as the program is running, but is not part of the essence of the program. Thus, when all of the non-daemon threads complete, the program is terminated. Conversely, if there are any non-daemon threads still running, the program doesn’t terminate. There is, for instance, a non-daemon thread that runs main( ).
//: c13:SimpleDaemons.java
// Daemon threads don't prevent the program from ending.
public class SimpleDaemons extends Thread {
public SimpleDaemons() {
setDaemon(true); // Must be called before start()
start();
}
public void run() {
while(true) {
try {
sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(this);
}
}
public static void main(String[] args) {
for(int i = 0; i < 10; i++)
new SimpleDaemons();
}
} ///:~
You must set the thread to be a daemon by calling setDaemon( ) before it is started. In run( ), the thread is put to sleep for a little bit. Once the threads are all started, the program terminates immediately, before any threads can print themselves, because there are no non-daemon threads (other than main( )) holding the program open. Thus, the program terminates without printing any output.
You can find out if a thread is a daemon by calling isDaemon( ). If a thread is a daemon, then any threads it creates will automatically be daemons, as the following example demonstrates:
//: c13:Daemons.java
// Daemon threads spawn other daemon threads.
import java.io.*;
import com.bruceeckel.simpletest.*;
class Daemon extends Thread {
private Thread[] t = new Thread[10];
public Daemon() {
setDaemon(true);
start();
}
public void run() {
for(int i = 0; i < t.length; i++)
t[i] = new DaemonSpawn(i);
for(int i = 0; i < t.length; i++)
System.out.println("t[" + i + "].isDaemon() = "
+ t[i].isDaemon());
while(true)
yield();
}
}
class DaemonSpawn extends Thread {
public DaemonSpawn(int i) {
start();
System.out.println("DaemonSpawn " + i + " started");
}
public void run() {
while(true)
yield();
}
}
public class Daemons {
private static Test monitor = new Test();
public static void main(String[] args) throws Exception {
Thread d = new Daemon();
System.out.println("d.isDaemon() = " + d.isDaemon());
// Allow the daemon threads to
// finish their startup processes:
Thread.sleep(1000);
monitor.expect(new String[] {
"d.isDaemon() = true",
"DaemonSpawn 0 started",
"DaemonSpawn 1 started",
"DaemonSpawn 2 started",
"DaemonSpawn 3 started",
"DaemonSpawn 4 started",
"DaemonSpawn 5 started",
"DaemonSpawn 6 started",
"DaemonSpawn 7 started",
"DaemonSpawn 8 started",
"DaemonSpawn 9 started",
"t[0].isDaemon() = true",
"t[1].isDaemon() = true",
"t[2].isDaemon() = true",
"t[3].isDaemon() = true",
"t[4].isDaemon() = true",
"t[5].isDaemon() = true",
"t[6].isDaemon() = true",
"t[7].isDaemon() = true",
"t[8].isDaemon() = true",
"t[9].isDaemon() = true"
}, Test.IGNORE_ORDER + Test.WAIT);
}
} ///:~
The Daemon thread sets its daemon flag to “true” and then spawns a bunch of other threads—which do not set themselves to daemon mode—to show that they are daemons anyway. Then it goes into an infinite loop that calls yield( ) to give up control to the other processes.
There’s nothing to keep the program from terminating once main( ) finishes its job, since there are nothing but daemon threads running. So that you can see the results of starting all the daemon threads, the main( ) thread is put to sleep for a second. Without this, you see only some of the results from the creation of the daemon threads. (Try sleep( ) calls of various lengths to see this behavior.)