当前位置: 首页 > 后端技术 > Java

Java守护线程

时间:2023-04-01 15:23:25 Java

Java,通过Thread类,我们可以创建两种线程,分为守护线程和用户线程。守护线程是所有非守护线程的保姆。当所有非守护线程都执行完或退出后,即使有守护线程在运行,JVM也会直接退出,所以守护线程通常用来处理一些辅助工作。反之,对于非守护线程,只要有一个在运行,JVM就不会退出。典型的守护线程如垃圾回收GC线程,当用户线程全部执行完后,GC就没有必要单独存在了,JVM直接退出。我们可以通过Thread对象的setDaemon(booleanon)方法来设置是否是守护线程。启动前要设置:Threadthread=newThread(runnable);thread.setDaemon(true);//true表示守护线程,false表示用户线程thread.start();需要注意的是,如果不显示setDaemon方法进行设置,则线程的模式取决于父线程是否为守护线程,即创建线程的线程。如果父线程是守护线程,则创建的线程默认是守护线程;如果父线程是用户线程,创建的线程默认是用户线程。这个从Thread类的init方法的源码可以看出:Threadparent=currentThread();this.daemon=parent.isDaemon();对于daemon的设置,保存在Thread对象的成员变量中,Thread提供了setter/getter:privatebooleandaemon=false;//是否是守护线程publicfinalvoidsetDaemon(booleanon){//SecurityManager安全检查,本文不讨论checkAccess();//检查线程是否已经启动,不能设置daemonif(isAlive()){thrownewIllegalThreadStateException();}daemon=on;}publicfinalbooleanisDaemon(){returndaemon;}setDaemon方法判断线程是否已经isAlive启动,启动状态不允许修改。抛出IllegalThreadStateException。然后我们用一个例子来验证守护线程和非守护线程的区别。以下是守护线程的示例:Threadt=newThread(()->{System.out.println("before");ThreadUtil.sleep(5000);System.out.println("after");});//显式设置daemon为trueet.setDaemon(true);t.start();ThreadUtil.sleep(1000);System.out.println("exit");输出:当线程设置为守护线程时可以发现beforeexit,一旦主线程执行完毕,程序退出,守护线程立即终止。这是一个非守护线程示例:Threadt=newThread(()->{System.out.println("before");ThreadUtil.sleep(5000);System.out.println("after");});//显式设置daemon为false.setDaemon(false);t.start();ThreadUtil.sleep(1000);System.out.println("exit");output:beforeexitafter虽然主线程已经执行完毕,但是创建的Non-daemon线程还在运行。具体来说,JVM是如何通过daemon字段来控制线程的呢?在JDK中找不到对应的源码。需要深入热点C++源码进行分析,后期有必要更新。