2-3 用户线程和守护线程
用户线程 vs 守护线程
Java 线程分为用户线程和守护线程,一般情况下不做特别说明配置,默认都是用户线程****。用户线程和守护线程是交替存在的
用户线程
是系统的工作线程,它会完成这个程序需要完成的业务操作。比如最基本的 main 方法,就是一个用户线程
public class DaemonDemo {
public static void main(String[] args) {
}
}
守护线程
是一种特殊的线程,为其它线程服务的,在后台默默地完成一些系统性的服务,比如垃圾回收线程就是最典型的例子
守护线程作为一个服务线程,没有服务对象就没有必要继续运行了,如果用户线程全部结束了,意味着程序需要完成的业务操作已经结束了,系统可以退出了。所以假如当系统只剩下守护线程的时候,java 虚拟机会自动退出
用户线程 vs 守护线程
有一个方法可以判断线程是否为守护线程
/**
* Tests if this thread is a daemon thread.
*
* @return <code>true</code> if this thread is a daemon thread;
* <code>false</code> otherwise.
* @see #setDaemon(boolean)
*/
public final boolean isDaemon() {
return daemon;
}
-
用户线程例子
由于用户线程是独立的,所以互不干扰,比如在 main 线程结束之后,用户设置的线程还可以单独存在:
public class DaemonDemo { public static void main(String[] args) { Thread t1 = new Thread(()->{ System.out.println(Thread.currentThread().getName()+"\t 开始运行, "+ (Thread.currentThread().isDaemon()?"守护线程":"用户线程")); while(true){ } },"t1"); t1.start(); try{ TimeUnit.SECONDS.sleep(3); }catch(InterruptedException e){ e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"\t ----end 主线程"); } }
输出结果
t1 开始运行, 用户线程 main ----end 主线程
实际上,如果不主动结束运行的话,t1 还是会一直执行,哪怕 main 线程已经之行结束了
-
守护线程例子
public class DaemonDemo { public static void main(String[] args) { Thread t1 = new Thread(()->{ System.out.println(Thread.currentThread().getName()+"\t 开始运行, "+ (Thread.currentThread().isDaemon()?"守护线程":"用户线程")); while(true){ } },"t1"); t1.setDaemon(true); t1.start(); try{ TimeUnit.SECONDS.sleep(3); }catch(InterruptedException e){ e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"\t ----end 主线程"); } }
将 t1 设置为守护线程,根据运行结果来看,当 main 线程(用户线程)执行结束,t1 也随之结束。
输出结果:
t1 开始运行, 守护线程 main ----end 主线程
小总结
-
如果用户线程全部结束意味着程序需要完成的业务操作己经结束了,守护线程随着 JVM 一同结束工作
-
setDaemon(true)
方法必须在start()
之前设置,否则报IllegalThreadStateException
异常