Java的线程分为两种,一个是用户线程,一个是守护线程。守护线程守护的对象就是用户线程,当用户线程结束后,守护它的守护线程也就会结束。二者的本质基本是一样的,唯一区别在于何时结束。
- 用户线程:直到自己运行完或者遇到异常就结束
- 守护线程:生命周期伴随着用户线程,随着用户线程结束而结束。
举个例子:运行状态的日志线程一般为守护线程,它时时记录运行状态的日志,守护着系统的主线程。当主线程结束或出现异常结束后,记录日志的守护线程就没有必要在记录,随着主线程结束而结束。
在java中将用户线程变为守护线程,调用setDaemon方法。
1 package com.my.day01.demo05; 2 3 public class DaemoTest { 4 5 public static void main(String[] args) { 6 7 Thread t = new Thread(new Runnable() { 8 9 @Override 10 public void run() { 11 12 try { 13 14 System.out.println(Thread.currentThread().getName()+" running"); 15 Thread.sleep(2000); 16 System.out.println("test"); 17 System.out.println(Thread.currentThread().getName()+" done"); 18 19 } catch (InterruptedException e) { 20 21 e.printStackTrace(); 22 } 23 } 24 }); 25 //设置为非守护线程,随着main线程的结束,守护线程也结束 26 t.setDaemon(false); 27 t.start(); 28 29 System.out.println(Thread.currentThread().getName()); 30 } 31 32 }
结果为:
main
Thread-0 running
test
Thread-0 done
在这个例子中,线程t为非守护线程,那么在main线程执行完后,线程t仍在执行。从输出的结果就可以看出来。
将线程t设为守护线程再来看一下
1 package com.my.day01.demo05; 2 3 public class DaemoTest { 4 5 public static void main(String[] args) { 6 7 Thread t = new Thread(new Runnable() { 8 9 @Override 10 public void run() { 11 12 try { 13 14 System.out.println(Thread.currentThread().getName()+" running"); 15 Thread.sleep(2000); 16 System.out.println("test"); 17 System.out.println(Thread.currentThread().getName()+" done"); 18 19 } catch (InterruptedException e) { 20 21 e.printStackTrace(); 22 } 23 } 24 }); 25 //设置为守护线程,随着main线程的结束,守护线程也结束 26 t.setDaemon(true); 27 t.start(); 28 29 System.out.println(Thread.currentThread().getName()); 30 } 31 32 }
结果为:
main
Thread-0 running
将线程设置为守护线程后,可以看到线程t没有运行完毕就随着main线程的结束而结束了。
再来看嵌套线程的守护线程,在main函数里面声明了一个名字叫Thread1的线程,在Thread1线程里面定义了一个名字为Thread2的线程。先将这个两个线程设为非守护线程,看结果。
1 package com.my.day01.demo05; 2 3 public class DaemoTest2 { 4 5 public static void main(String[] args) { 6 7 Thread t = new Thread(new Runnable() { 8 @Override 9 public void run() { 10 11 Thread tt = new Thread(new Runnable() { 12 @Override 13 public void run() { 14 System.out.println(Thread.currentThread().getName() + "running"); 15 try { 16 Thread.sleep(20_000); 17 } catch (InterruptedException e) { 18 19 e.printStackTrace(); 20 } 21 System.out.println(Thread.currentThread().getName() + "done"); 22 } 23 24 }, "Thread2"); 25 26 tt.setDaemon(false); 27 tt.start(); 28 29 System.out.println(Thread.currentThread().getName() + "running"); 30 try { 31 32 Thread.sleep(10_000); 33 34 } catch (InterruptedException e) { 35 e.printStackTrace(); 36 } 37 System.out.println(Thread.currentThread().getName() + "done"); 38 } 39 }, "Thread1"); 40 41 // 设置为非守护线程,随着main线程的结束,守护线程也结束 42 t.setDaemon(false); 43 t.start(); 44 45 System.out.println(Thread.currentThread().getName()); 46 47 } 48 }
结果:
main
Thread1running
Thread2running
Thread1done
Thread2done
main线程执行完后,Thread2和Thread1交替执行。再来看看将子线程Thread2设为守护线程,输出的结果为
1 main 2 Thread1running 3 Thread2running 4 Thread1done
可以看到子线程Thread2守护Thread1,当Thread1结束后,Thread2也随之结束。
如果将线程Thread1也设置为守护线程,再来看结果
main
Thread1守护的是main线程,main线程一结束Thread1也随之结束。Thread1的子线程Thread2也跟着结束(这就是说守护线程具有继承性,如果一个线程为守护线程,那么它的子线程都为守护线程)
总结:
1.守护线程守护的是它所在声明的那个线程。
2.当指定一个线程为守护线程后,它的子线程都是守护线程。