在Java的线程机制中,有两类线程:
- User Thread(用户线程)
- Daemon Thread(守护线程) 。
Daemon Thread的作用是为其他线程的运行提供服务,比如说GC线程。其实User Thread线程和Daemon Thread守护线程本质上来说去没啥区别的,唯一的区别之处就在虚拟机的离开时候:如果User Thread全部撤离,那么Daemon Thread也就没啥线程好服务的了,所以虚拟机也就退出了。只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作。守护线程最典型的应用就是 GC (垃圾回收器)。
守护线程并非只有虚拟机内部可以提供,用户也可以自行的设定守护线程,可以通过Thread的setDaemon方法来设置,这个值的默认值是false,即默认是用户线程
- thread.setDaemon(true)必须在thread.start()之前设置,否则会跑出一个IllegalThreadStateException异常。你不能把正在运行的常规线程设置为守护线程。
- 在Daemon线程中产生的新线程也是Daemon的。 (这一点又是与守护线程有着本质的区别了:守护进程fork()出来的子进程不再是守护进程,尽管它把父进程的进程相关信息复制过去了,但是子进程的进程的父进程不是init进程,所谓的守护进程本质上说就是“父进程挂掉,init收养,然后文件0,1,2都是/dev/null,当前目录到/”)
- 不是所有的应用都可以分配给Daemon线程来进行服务,比如读写操作或者计算逻辑。因为在Daemon Thread还没来的及进行操作时,虚拟机可能已经退出了。
class TestRunnable implements Runnable{
public void run(){
try{
Thread.sleep(1000);//守护线程阻塞1秒后运行
System.out.println("this thread is running");
catch(IOException e){
e.printStackTrace();
}
}
}
public class TestDemo{
public static void main(String[] args) throws InterruptedException
{
Runnable tr=new TestRunnable();
Thread thread=new Thread(tr);
thread.setDaemon(true); //设置守护线程
thread.start(); //开始执行分进程
System.out.println("main thread is finished");
}
}
运行结果:只输出了“main thread is finished” 因为设置了thread.setDaemon(true); 当没有正在执行的用户线程的时候,守护线程也会结束。
如果把thread.setDaemon(true); 注释掉,会同时输出:"main thread is finished"和"this thread is running"