Java守护线程和用户线程的区别

目录
  • 守护线程定义
  • 创建守护线程
    • 将线程池设置为守护线程
  • 守护线程 VS 用户线程
    • 用户线程
    • 守护线程
    • 守护线程注意事项
  • 总结

前言:

在 Java 语言中,线程分为两类:用户线程和守护线程,默认情况下我们创建的线程或线程池都是用户线程,所以用户线程也被称之为普通线程。

想要查看线程到底是用户线程还是守护线程,可以通过 Thread.isDaemon() 方法来判断,如果返回的结果是 true 则为守护线程,反之则为用户线程。

我们来测试一下默认情况下线程和线程池属于哪种线程类型?测试代码如下:

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 线程类型:守护线程 OR 用户线程
 */
public class ThreadType {
    public static void main(String[] args) {
        // 创建线程
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                //...
            }
        });
        // 创建线程池
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(10, 10,
                0, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100));
        threadPool.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("ThreadPool 线程类型:" +
                        (Thread.currentThread().isDaemon() == true ? "守护线程" : "用户线程"));
            }
        });
        System.out.println("Thread 线程类型:" +
                (thread.isDaemon() == true ? "守护线程" : "用户线程"));
        System.out.println("main 线程类型:" +
                (Thread.currentThread().isDaemon() == true ? "守护线程" : "用户线程"));
    }
}

以上程序的执行结果如下图所示: 

从上述结果可以看出,默认情况下创建的线程和线程池都是用户线程。

守护线程定义

守护线程(Daemon Thread)也被称之为后台线程或服务线程,守护线程是为用户线程服务的,当程序中的用户线程全部执行结束之后,守护线程也会跟随结束。 守护线程的角色就像“服务员”,而用户线程的角色就像“顾客”,当“顾客”全部走了之后(全部执行结束),那“服务员”(守护线程)也就没有了存在的意义,所以当一个程序中的全部用户线程都结束执行之后,那么无论守护线程是否还在工作都会随着用户线程一块结束,整个程序也会随之结束运行。

创建守护线程

我们可以通过 Thread.setDaemon(true) 方法将线程设置为守护线程,比如以下代码的实现:

public static void main(String[] args) {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            //...
        }
    });
    // 设置线程为守护线程
    thread.setDaemon(true);
    System.out.println("Thread 线程类型:" +
                       (thread.isDaemon() == true ? "守护线程" : "用户线程"));
    System.out.println("main 线程类型:" +
                       (Thread.currentThread().isDaemon() == true ? "守护线程" : "用户线程"));
}

以上程序的执行结果如下图所示: 

将线程池设置为守护线程

要把线程池设置为守护线程相对来说麻烦一些,需要将线程池中的所有线程都设置成守护线程,这个时候就需要使用线程工厂 ThreadFactory 来设置了(线程池中的所有线程都是通过线程工厂创建的),

它的具体实现代码如下:

public static void main(String[] args) throws InterruptedException {
    // 线程工厂(设置守护线程)
    ThreadFactory threadFactory = new ThreadFactory() {
        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r);
            // 设置为守护线程
            thread.setDaemon(true);
            return thread;
        }
    };
    // 创建线程池
    ThreadPoolExecutor threadPool = new ThreadPoolExecutor(10, 10,
                                                           0, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100), threadFactory);
    threadPool.submit(new Runnable() {
        @Override
        public void run() {
            System.out.println("ThreadPool 线程类型:" +
                               (Thread.currentThread().isDaemon() == true ? "守护线程" : "用户线程"));
        }
    });
    Thread.sleep(2000);
}

以上程序的执行结果如下图所示: 

守护线程 VS 用户线程

通过前面的内容我们了解了什么是用户线程和守护线程了,那二者有什么区别呢?接下来我们用一个小示例来观察一下。 接下来我们将创建一个线程,分别将这个线程设置为用户线程和守护线程,在每个线程中执行一个 for 循环,总共执行 10 次信息打印,每次打印之后休眠 100 毫秒,来观察程序的运行结果。

用户线程

新建的线程默认就是用户线程,因此我们无需对线程进行任何特殊的处理,执行 for 循环即可(总共执行 10 次信息打印,每次打印之后休眠 100 毫秒),

实现代码如下:

public static void main(String[] args) throws InterruptedException {
    // 创建用户线程
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 1; i <= 10; i++) {
                // 打印 i 信息
                System.out.println("i:" + i);
                try {
                    // 休眠 100 毫秒
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    });
    // 启动线程
    thread.start();
}

以上程序的执行结果如下图所示: 

从上述结果可以看出,当程序执行完 10 次打印之后才会正常结束进程。

守护线程

public static void main(String[] args) throws InterruptedException {
    // 创建守护线程
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 1; i <= 10; i++) {
                // 打印 i 信息
                System.out.println("i:" + i);
                try {
                    // 休眠 100 毫秒
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    });
    // 设置为守护线程
    thread.setDaemon(true);
    // 启动线程
    thread.start();
}

以上程序执行结果如下图所示: 

从上述结果可以看出,当线程设置为守护线程之后,整个程序不会等守护线程 for 循环 10 次之后再进行关闭,而是当主线程结束之后,守护线程一次循环都没执行就结束了,由此可以看出守护线程和用户线程的不同。

守护线程注意事项

守护线程的设置 setDaemon(true) 必须要放在线程的 start() 之前,否则程序会报错。也就是说在运行线程之前,一定要先确定线程的类型,并且线程运行之后是不允许修改线程的类型的。 接下来我们来演示一下,如果在程序运行执行再设置线程的类型会出现什么问题?

演示代码如下:

public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 1; i <= 10; i++) {
                // 打印 i 信息
                System.out.println("i:" + i + ",isDaemon:" +
                            Thread.currentThread().isDaemon());
                try {
                    // 休眠 100 毫秒
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    });
    // 启动线程
    thread.start();
    // 设置为守护线程
    thread.setDaemon(true);
}

以上程序执行结果如下图所示: 

从上述结果可以看出,当我们将 setDaemon(true) 设置在 start() 之后,不但程序的执行会报错,而且设置的守护线程也不会生效。

总结

在 Java 语言中线程分为两类:用户线程和守护线程,默认情况下我们创建的线程或线程池都是用户线程,守护线程是为用户线程服务的,当一个程序中的所有用户线程都执行完成之后程序就会结束运行,程序结束运行时不会管守护线程是否正在运行,由此我们可以看出守护线程在 Java 体系中权重是比较低的,这就是守护线程和用户线程的区别。

到此这篇关于Java守护线程和用户线程的区别的文章就介绍到这了,更多相关Java 守护线程内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • java高并发的用户线程和守护线程详解

    目录 程序只有守护线程时,系统会自动退出 设置守护线程,需要在start()方法之前进行 线程daemon的默认值 总结 守护线程是一种特殊的线程,在后台默默地完成一些系统性的服务,比如垃圾回收线程.JIT线程都是守护线程.与之对应的是用户线程,用户线程可以理解为是系统的工作线程,它会完成这个程序需要完成的业务操作.如果用户线程全部结束了,意味着程序需要完成的业务操作已经结束了,系统可以退出了.所以当系统只剩下守护进程的时候,java虚拟机会自动退出. java线程分为用户线程和守护线程,线程的

  • 浅谈java中守护线程与用户线程

    Java线程分为两类分别为daemon线程(守护线程)和User线程(用户线程),在JVM启动时候会调用main函数,main函数所在的线程是一个用户线程,这个是我们可以看到的线程,其实JVM内部同时还启动了好多守护线程,比如垃圾回收线程.那么守护线程和用户线程有什么区别那?区别之一是当最后一个非守护线程结束时候,JVM会正常退出,而不管当前是否有守护线程,也就是说守护线程是否结束并不影响JVM的退出.言外之意是只要有一个用户线程还没结束正常情况下JVM就不会退出. 那么Java中如何创建一个守

  • 详解Java线程-守护线程与用户线程

    干java 开发这么多年, 之前一直没留意java 进程还区分守护进程和用户进程.守护进程这个概念最早还是在linux系统中接触的,直到近期使用java开发心跳检测功能时,使用Timer时才发现原来java也有守护线程的概念. 1. Java 线程 1.1 守护线程与用户线程 Java 线程分为守护线程(DaemonThread) 和 用户线程(UserThread)两类. 通常情况下,我们使用Thread 创建的线程在默认情况下都属于用户线程, 当在启动线程之前, 执行thread.setDa

  • Java中用户线程与守护线程的使用区别

    目录 1.默认用户线程 2.主动修改为守护线程 2.1 设置线程为守护线程 2.2 设置线程池为守护线程 3.守护线程 VS 用户线程 3.1 用户线程 3.2 守护线程 3.3 小结 4.守护线程注意事项 4.1 setDaemon 执行顺序 4.2 守护线程的子线程 4.3 join 与守护线程 5.守护线程应用场景 6.守护线程的执行优先级 7.总结 前言; 在 Java 语言中线程分为两类:用户线程和守护线程,而二者之间的区别却鲜有人知,所以本文磊哥带你来看二者之间的区别,以及守护线程需

  • Java守护线程和用户线程的区别

    目录 守护线程定义 创建守护线程 将线程池设置为守护线程 守护线程 VS 用户线程 用户线程 守护线程 守护线程注意事项 总结 前言: 在 Java 语言中,线程分为两类:用户线程和守护线程,默认情况下我们创建的线程或线程池都是用户线程,所以用户线程也被称之为普通线程. 想要查看线程到底是用户线程还是守护线程,可以通过 Thread.isDaemon() 方法来判断,如果返回的结果是 true 则为守护线程,反之则为用户线程. 我们来测试一下默认情况下线程和线程池属于哪种线程类型?测试代码如下:

  • 深入探究Java线程与进程有哪些区别

    目录 一.进程线和程的概念 二.为什么要有线程 三.进程和线程的关系 四.线程和进程的区别(重点) 五.用户线程和守护线程区别 一.进程线和程的概念 线程: 一个线程是一个独立的执行流,每个线程之间都可以按照顺讯执行自己的代码. 多个线程之间 “同时” 执行着多份代码 public class ThreadDemo { public static void main(String[] args) { Thread thread = new Thread(new Runnable() { @Ove

  • 谈谈Java中的守护线程与普通线程

    守护线程与普通线程的唯一区别是:当JVM中所有的线程都是守护线程的时候,JVM就可以退出了:如果还有一个或以上的非守护线程则不会退出.(以上是针对正常退出,调用System.exit则必定会退出) 所以setDeamon(true)的唯一意义就是告诉JVM不需要等待它退出,让JVM喜欢什么退出就退出吧,不用管它. 守护线程在没有用户线程可服务时自动离开,在Java中比较特殊的线程是被称为守护(Daemon)线程的低级别线程.这个线程具有最低的优先级,用于为系统中的其它对象和线程提供服务.将一个用

  • Java 守护线程_动力节点Java学院整理

    估计学过Unix开发但是没有细致学习Java的同学们会疑惑了,操作系统里面是没有所谓的守护线程的概念,只有守护进程一说,但是Java语言机制是构建在JVM的基础之上的,意思是Java平台把操作系统的底层给屏蔽起来,所以它可以在它自己的虚拟的平台里面构造出对自己有利的机制,而语言或者说平台的设计者多多少少是收到Unix思想的影响,而守护线程机制又是对JVM这样的平台凑合,于是守护线程应运而生. Daemon的作用是为其他线程的运行提供服务,比如说GC线程.其实User Thread线程和Daemo

  • Java守护线程实例详解_动力节点Java学院整理

    在Java中有两类线程:User Thread(用户线程).Daemon Thread(守护线程) 用个比较通俗的比如,任何一个守护线程都是整个JVM中所有非守护线程的保姆: 只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作:只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作. Daemon的作用是为其他线程的运行提供便利服务,守护线程最典型的应用就是 GC (垃圾回收器),它就是一个很称职的守护者. User和Daemon两者几乎没有区别,唯一的不同之处就在

  • Java守护线程用法实例分析

    本文实例讲述了Java守护线程用法.分享给大家供大家参考,具体如下: 一 点睛 针对守护线程,只要有一个用户线程在执行,这个进程就不会结束. 当线程中只剩下守护线程时,JVM会自动退出,反之,如果还有其他任何用户线程存在,JVM都不会退出. 二 代码 public class ThreadDaemon { public static void main( String args[] ) { ThreadTest t = new ThreadTest(); Thread tt = new Thre

随机推荐