java-Daemon线程(守护线程)

251 阅读2分钟

什么是Daemon线程

Daemon线程也是守护线程,它是一种支持型的线程, 主要用在程序的后台调度以及一些支持性(服务性)的工作,常见的例子:JVM中垃圾回线程就是典型的守护线程

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

守护线程与用户线程的区别发生在JVM的离开

  • 可以说JVM想要运行,用户线程也必须运行
  • 守护线程是服务于用户线程的,如果用户线程不在了,那么守护线程的存在是没有意义的,此时该程序(进程)就没有运行的必要了,JVM也就退出了
  • 守护线程的优先级是低于用户线程的

用户设置守护线程

守护线程不是固定死的,用户可以将自己的线程(服务性质的线程)设置为守护线程,设置方法为Thread.setDaemon()方法,源码为:

public final void setDaemon(boolean on) {
    checkAccess();
    if (isAlive()) {
        throw new IllegalThreadStateException();
    }
    //daemon属性默认为false
    daemon = on;
}

我们可以通过setDaemon(true)来设置当前线程为守护线程,但是需要注意的是,该方法必须在线程启动前的执行,即执行在线程NEW状态之后,RUNNABLE之前的, 因为源码中的isAlive() 会检测当前线程是否是活跃状态,即启动或正常执行状态,如果isAlive()为true,则抛出异常:

 //创建线程
 Thread daemonTread = new Thread();
 //设置线程为守护线程
 daemonThread.setDaemon(true);
 // 返回 true 则为守护线程
 daemonThread.isDaemon();
在使用守护线程时需要注意一下几点:

(1) thread.setDaemon(true)必须在thread.start()之前设置,否则会跑出一个IllegalThreadStateException异常。你不能把正在运行的常规线程设置为守护线程。

(2) 在Daemon线程中产生的新线程也是Daemon的。

(3) 守护线程应该永远不去访问固有资源,如文件、数据库,因为它会在任何时候甚至在一个操作的中间发生中断。

  • 前面说到了,服务性质的线程可以设置为守护线程,类似于读写操作、计算逻辑。

    • 如果带有这些操作的线程被设置为守护线程,在它执行时,有用户线程在执行的话还好说,但是可能会出现该线程创建完成且启动但是还没有执行到读写操作,尤其是写操作,可能是作为某个程序的最后一步执行,那么此时该程序中的用户线程都已经执行完毕了,而main函数只负责创建守护线程并启动,然后,main线程也会关闭,JVM发现没有用户线程了,便会退出,守护线程也会终止,此时可能还来不及进行写操作。

Daemon线程的意义--监控、回收等后台服务,优先级比较低,无用户线程时,守护线程自尽,JVM exist