class="MsoNormal">线程分为两种:守护线程和用户线程(也叫非守护线程)。
?
可以通过Thread的setDaemon(boolean on)方法将其设定为守护线程或用户线程。
setDaemon方法必须在线程启动前被调用。不然会产生IllegalThreadStateException异常。
并且,守护线程具有传递性,即如果一个线程是守护线程,那么它的子线程也会是守护线程。
?
守护线程是为了服务于用户线程而存在的,所以当Java的执行环境结束(调用System.exit方法停止JVM时,或者所有非守护线程都结束时)守护线程也会退出。
?
有一点注意了,在application中要慎用用户线程,因为当JVM中存在alive的用户线程时,有可能会出现服务停止超时的情况。(当然,有些服务停止时会去调用System.exit方法,就不会有容器停止超时的情况出现)。
比如,GlassFish3.1.2的JavaEE6的Cluster停止的时候就不会去调用System.exit方法。
?
但是,守护线程也不是使用与所有的情况下的。比如:读写操作或者逻辑计算
我们看下面的一个例子
public class DaemonThread extends Thread { public void run() { for (int i = 0; i < 999; i++) { System.out.println("This is Daemon Thread:" + i); try { Thread.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class UserThread extends Thread { public void run() { for (int i = 0; i < 5; i++) { System.out.println("This is User Thread:" + i); try { Thread.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class HookTest { public static void main(String[] args) { Thread t1 = new DaemonThread(); Thread t2 = new UserThread(); t1.setDaemon(true); t1.start(); t2.start(); } }
?
?此时,console中输出如下:
This is Daemon Thread:0 This is User Thread:0 This is User Thread:1 This is Daemon Thread:1 This is User Thread:2 This is Daemon Thread:2 This is User Thread:3 This is Daemon Thread:3 This is User Thread:4 This is Daemon Thread:4 This is Daemon Thread:5
?
可以看到:程序只保证了User Thread的执行,Daemon Thread并没有执行完成就退出了。
?
那是不是这个问题不能解决呢?当然不是,使用Runtime的addShutdownHook(Thread hook)方法就可以!
addShutdownHook方法会在JVM停止前被调用,也就是说,JVM会等addShutdownHook中的Thread执行结束后才关闭。这样,就可以等用户的操作都结束后,才退出JVM。
?
上面的那个例子,Main函数就可以改写为以下的样子:?
public static void main(String[] args){ Runtime.getRuntime().addShutdownHook( new Thread(){ public void run(){ System.out.println("This is Shutdown Hook!!!"); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } } ); Thread t1 = new DaemonThread(); Thread t2 = new UserThread(); t1.setDaemon(true);//设置为守护程序 t1.start(); t2.start(); }
?此时,consloe中输出如下:
This is Daemon Thread:0 This is User Thread:0 This is User Thread:1 This is Daemon Thread:1 This is User Thread:2 This is Daemon Thread:2 This is User Thread:3 This is Daemon Thread:3 This is User Thread:4 This is Daemon Thread:4 This is Daemon Thread:5 This is Shutdown Hook!!! This is Daemon Thread:6 …… This is Daemon Thread:996 This is Daemon Thread:997 This is Daemon Thread:998
?可以看到:User Thread执行结束后,JVM并不是马上就退出,而是调用了addShutdownHook,sleep了10000ms后再退出。
?