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.)
No comments:
Post a Comment