千家信息网

怎么理解java高并发的用户线程和守护线程

发表于:2024-09-21 作者:千家信息网编辑
千家信息网最后更新 2024年09月21日,这篇文章主要讲解了"怎么理解java高并发的用户线程和守护线程",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"怎么理解java高并发的用户线程和守护线程
千家信息网最后更新 2024年09月21日怎么理解java高并发的用户线程和守护线程

这篇文章主要讲解了"怎么理解java高并发的用户线程和守护线程",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"怎么理解java高并发的用户线程和守护线程"吧!

守护线程是一种特殊的线程,在后台默默地完成一些系统性的服务,比如垃圾回收线程、JIT线程都是守护线程。与之对应的是用户线程,用户线程可以理解为是系统的工作线程,它会完成这个程序需要完成的业务操作。如果用户线程全部结束了,意味着程序需要完成的业务操作已经结束了,系统可以退出了。所以当系统只剩下守护进程的时候,java虚拟机会自动退出。

java线程分为用户线程和守护线程,线程的daemon属性为true表示是守护线程,false表示是用户线程。

下面我们来看一下守护线程的一些特性。

程序只有守护线程时,系统会自动退出

package com.itsoku.chat03;     /**      * 微信公众号:路人甲Java,专注于java技术分享(带你玩转 爬虫、分布式事务、异步消息服务、任务调度、分库分表、大数据等),喜欢请关注!  */        public class Demo1 {         public static class T1 extends Thread {           public T1(String name) {             super(name);            }               @Override               public void run() {                  System.out.println(this.getName() + "开始执行," + (this.isDaemon() ? "我是守护线程" : "我是用户线程"));               while (true) ;                }           }           public static void main(String[] args) {               T1 t1 = new T1("子线程1");           t1.start();             System.out.println("主线程结束");      }       }

运行上面代码,结果如下:

可以看到主线程已经结束了,但是程序无法退出,原因:子线程1是用户线程,内部有个死循环,一直处于运行状态,无法结束。

再看下面的代码:

package com.itsoku.chat03;     /**      * 微信公众号:路人甲Java,专注于java技术分享(带你玩转 爬虫、分布式事务、异步消息服务、任务调度、分库分表、大数据等),喜欢请关注!  */        public class Demo2 {         public static class T1 extends Thread {           public T1(String name) {             super(name);            }               @Override               public void run() {                  System.out.println(this.getName() + "开始执行," + (this.isDaemon() ? "我是守护线程" : "我是用户线程"));               while (true) ;                }           }           public static void main(String[] args) {               T1 t1 = new T1("子线程1");           t1.setDaemon(true);             t1.start();             System.out.println("主线程结束");      }       }

运行结果:

程序可以正常结束了,代码中通过 t1.setDaemon(true); 将t1线程设置为守护线程,main方法所在的主线程执行完毕之后,程序就退出了。

结论:当程序中所有的用户线程执行完毕之后,不管守护线程是否结束,系统都会自动退出。

设置守护线程,需要在start()方法之前进行

package com.itsoku.chat03; import java.util.concurrent.TimeUnit;      /**      * 微信公众号:路人甲Java,专注于java技术分享(带你玩转 爬虫、分布式事务、异步消息服务、任务调度、分库分表、大数据等),喜欢请关注!  */        public class Demo3 {         public static void main(String[] args) {               Thread t1 = new Thread() {                 @Override                   public void run() {                      try {                          TimeUnit.SECONDS.sleep(10);                     } catch (InterruptedException e) {                      e.printStackTrace();                    }                   }               };              t1.start();             t1.setDaemon(true);         }       }

t1.setDaemon(true);是在t1的start()方法之后执行的,执行会报异常,运行结果如下:

线程daemon的默认值

我们看一下创建线程源码,位于Thread类的init()方法中:

Thread parent = currentThread(); this.daemon = parent.isDaemon();

dameon的默认值为为父线程的daemon,也就是说,父线程如果为用户线程,子线程默认也是用户现场,父线程如果是守护线程,子线程默认也是守护线程。

示例代码:

package com.itsoku.chat03;  import java.util.concurrent.TimeUnit;      /**      * 微信公众号:路人甲Java,专注于java技术分享(带你玩转 爬虫、分布式事务、异步消息服务、任务调度、分库分表、大数据等),喜欢请关注!  */        public class Demo4 {         public static class T1 extends Thread {           public T1(String name) {             super(name);            }               @Override               public void run() {                  System.out.println(this.getName() + ".daemon:" + this.isDaemon());                }           }           public static void main(String[] args) throws InterruptedException {         System.out.println(Thread.currentThread().getName() + ".daemon:" + Thread.currentThread().isDaemon());            T1 t1 = new T1("t1");             t1.start();             Thread t2 = new Thread() {                 @Override                   public void run() {                      System.out.println(this.getName() + ".daemon:" + this.isDaemon());                        T1 t3 = new T1("t3");                     t3.start();                 }               };              t2.setName("t2");             t2.setDaemon(true);             t2.start();             TimeUnit.SECONDS.sleep(2);          }       }

运行代码,输出:

main.daemon:false
t1.daemon:false
t2.daemon:true
t3.daemon:true

t1是由主线程(main方法所在的线程)创建的,main线程是t1的父线程,所以t1.daemon为false,说明t1是用户线程。

t2线程调用了 setDaemon(true);将其设为守护线程,t3是由t2创建的,所以t3默认线程类型和t2一样,t2.daemon为true。

感谢各位的阅读,以上就是"怎么理解java高并发的用户线程和守护线程"的内容了,经过本文的学习后,相信大家对怎么理解java高并发的用户线程和守护线程这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

0