JAVA 线程之守护线程Daemon Thread

本文介绍了Java中的守护线程和用户线程的区别,守护线程在所有非守护线程结束后随虚拟机一同退出。内容包括如何将线程设置为守护线程、编写守护线程实例及使用jstack生成线程快照分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在Java中有两类线程:

用户线程 (User Thread) 和 守护线程 (Daemon Thread)。

守护线程

  1. 是指在程序运行的时候在后台提供一种通用服务的线程,并不属于程序中不可或缺的部分

  2. 当所有的非守护线程结束时,程序也就终止了,同时会杀死进程中的所有守护线程

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

唯一的不同之处就在于虚拟机的离开:如果用户线程已经全部退出运行了,只剩下守护线程存在了,虚拟机也就退出了。 因为没有了被守护者,守护线程也就没有工作可做了,也就没有继续运行程序的必要了。

将线程转换为守护线程

通过调用Thread对象的setDaemon(true)方法来实现。在使用守护线程时需要注意一下几点:

  1. 必须在start()方法之前设置

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

  2. 在Daemon线程中产生的新线程也是Daemon的

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

编写实例

  1. 编写DeamonThread类实现往文件中写入数据的功能
  2. 在主线程中将DeamonThread设置为守护线程 并且使用键盘输入模拟阻塞状态
  3. 当从键盘输入后从阻塞状态进入运行状态 主线程执行结束 守护线程也结束

DeamonThread :

package thread.demo3;

import java.io.*;

/**
 * 守护线程DeamonThread
 * Created by heqianqian on 2017/4/15.
 */
public class DeamonThread implements Runnable {
    private int count = 0;

    @Override
    public void run() {
        System.out.println("Deamon Thread Running....");
        File file = new File("Base/file/deamon/file.txt");
        OutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(file, true);
            while (count < 999) {
                outputStream.write(("word:"+count+"\r\n").getBytes());
                System.out.println(Thread.currentThread().getName()+" write word "+count++);
                Thread.sleep(1000);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (outputStream!=null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println("Deamon Thread Over!");
    }
}

Main:

package thread.demo3;

import java.util.Scanner;

/**
 * Main
 * Created by heqianqian on 2017/4/15.
 */
public class Main {
    public static void main(String[] args) {
        System.out.println("Main Thread Running....");
        DeamonThread deamonThread = new DeamonThread();
        Thread thread = new Thread(deamonThread);
        thread.setDaemon(true);//设置为守护线程 且必须在start前调用
        thread.start();

        Scanner scanner = new Scanner(System.in);
        scanner.next();//模拟阻塞

        System.out.println("Main Thread Over!");
    }
}

运行结果:
这里写图片描述

file.txt文件内容:

这里写图片描述

使用jstack生成线程快照

运行程序后 打开任务管理器 找到当前程序的PID

这里写图片描述

打开CMD 输入

jstack -l pid

可以看到快照结果

这里写图片描述

我们可以分析一下


C:\Users\heqianqian>jstack -l 10092
2017-04-15 09:54:03
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.92-b14 mixed mode):

"RMI RenewClean-[localhost:52353]" #18 daemon prio=5 os_prio=0 tid=0x00000000173ac000 nid=0x239c in Object.wait() [0x0000000017b0f000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
        - locked <0x00000000d01df4c0> (a java.lang.ref.ReferenceQueue$Lock)
        at sun.rmi.transport.DGCClient$EndpointEntry$RenewCleanThread.run(DGCClient.java:553)
        at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
        - None

"RMI Scheduler(0)" #17 daemon prio=5 os_prio=0 tid=0x00000000173a9000 nid=0x255c waiting on condition [0x0000000017a0e000]
   java.lang.Thread.State: TIMED_WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000d02c2350> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
        at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
        at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
        - None

"GC Daemon" #14 daemon prio=2 os_prio=-2 tid=0x000000001648b800 nid=0x2428 in Object.wait() [0x0000000016f0e000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        at sun.misc.GC$Daemon.run(GC.java:117)
        - locked <0x00000000d02c2510> (a sun.misc.GC$LatencyLock)

   Locked ownable synchronizers:
        - None

"RMI Reaper" #13 prio=5 os_prio=0 tid=0x0000000016607000 nid=0x2268 in Object.wait() [0x0000000016e0f000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000d01dfac0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
        - locked <0x00000000d01dfac0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
        at sun.rmi.transport.ObjectTable$Reaper.run(ObjectTable.java:351)
        at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
        - None

"RMI TCP Accept-0" #12 daemon prio=5 os_prio=0 tid=0x000000001655e000 nid=0x24a0 runnable [0x0000000016d0e000]
   java.lang.Thread.State: RUNNABLE
        at java.net.DualStackPlainSocketImpl.accept0(Native Method)
        at java.net.DualStackPlainSocketImpl.socketAccept(DualStackPlainSocketImpl.java:131)
        at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
        at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:199)
        - locked <0x00000000d01df1b0> (a java.net.SocksSocketImpl)
        at java.net.ServerSocket.implAccept(ServerSocket.java:545)
        at java.net.ServerSocket.accept(ServerSocket.java:513)
        at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:400)
        at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(TCPTransport.java:372)
        at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
        - None

"RMI TCP Accept-34855" #11 daemon prio=5 os_prio=0 tid=0x0000000016243800 nid=0x2338 runnable [0x0000000016c0f000]
   java.lang.Thread.State: RUNNABLE
        at java.net.DualStackPlainSocketImpl.accept0(Native Method)
        at java.net.DualStackPlainSocketImpl.socketAccept(DualStackPlainSocketImpl.java:131)
        at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
        at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:199)
        - locked <0x00000000d0211318> (a java.net.SocksSocketImpl)
        at java.net.ServerSocket.implAccept(ServerSocket.java:545)
        at java.net.ServerSocket.accept(ServerSocket.java:513)
        at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:400)
        at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(TCPTransport.java:372)
        at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
        - None

"Service Thread" #9 daemon prio=9 os_prio=0 tid=0x0000000016296000 nid=0x284c runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"C1 CompilerThread2" #8 daemon prio=9 os_prio=2 tid=0x000000001621b000 nid=0x27c0 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"C2 CompilerThread1" #7 daemon prio=9 os_prio=2 tid=0x0000000016215800 nid=0x286c waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"C2 CompilerThread0" #6 daemon prio=9 os_prio=2 tid=0x0000000014c8d000 nid=0x26f0 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x0000000014c8b800 nid=0x27a0 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x0000000014c40000 nid=0x2780 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x0000000002ebd000 nid=0x279c in Object.wait() [0x0000000015faf000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
        - locked <0x00000000d02c32b0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

   Locked ownable synchronizers:
        - None

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x0000000002eb2000 nid=0x26e0 in Object.wait() [0x0000000015eaf000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
        - locked <0x00000000d02ea1c8> (a java.lang.ref.Reference$Lock)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

   Locked ownable synchronizers:
        - None

"main" #1 prio=5 os_prio=0 tid=0x0000000002dc2800 nid=0x2844 in Object.wait() [0x00000000029ff000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        at com.intellij.execution.rmi.RemoteServer.start(RemoteServer.java:86)
        - locked <0x00000000d02c3350> (a java.lang.Object)
        at org.jetbrains.idea.maven.server.RemoteMavenServer.main(RemoteMavenServer.java:22)

   Locked ownable synchronizers:
        - None

"VM Thread" os_prio=2 tid=0x0000000014bf7000 nid=0x2794 runnable

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x0000000002dd8800 nid=0x2878 runnable

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x0000000002dda000 nid=0x2804 runnable

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x0000000002ddb800 nid=0x1d9c runnable

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x0000000002ddd000 nid=0x25e8 runnable

"VM Periodic Task Thread" os_prio=2 tid=0x00000000162dc000 nid=0x27c4 waiting on condition

JNI global references: 236


C:\Users\heqianqian>
  1. Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.92-b14 mixed mode)
    线程块运行在java虚拟机hotspot上 是64位的服务端
  2. 接下来是一些java自带的守护进程
    比如GC线程

这里写图片描述

可以看到是deamon线程 优先级是2 当前状态为有时间的等待状态

Locked ownable synchronizers 是否处于同步块中

最后显示的是我们的主线程

这里写图片描述

可以看到主线程并不是一个守护线程 并且处于等待状态 原因是我们的键盘输入阻塞了主线程

jstack使用参数

这里写图片描述


参考文章:

http://www.cnblogs.com/diyingyun/archive/2011/12/25/2300998.html

http://www.cnblogs.com/super-d2/p/3348183.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值