本文共 10773 字,大约阅读时间需要 35 分钟。
在Java中有两类线程:
用户线程 (User Thread) 和 守护线程 (Daemon Thread)。
是指在程序运行的时候在后台提供一种通用服务的线程,并不属于程序中不可或缺的部分
当所有的非守护线程结束时,程序也就终止了,同时会杀死进程中的所有守护线程
唯一的不同之处就在于虚拟机的离开:如果用户线程已经全部退出运行了,只剩下守护线程存在了,虚拟机也就退出了。 因为没有了被守护者,守护线程也就没有工作可做了,也就没有继续运行程序的必要了。
通过调用Thread对象的setDaemon(true)方法来实现。在使用守护线程时需要注意一下几点:
必须在start()方法之前设置
thread.setDaemon(true)必须在thread.start()之前设置,否则会跑出一个IllegalThreadStateException异常。你不能把正在运行的常规线程设置为守护线程。
在Daemon线程中产生的新线程也是Daemon的
守护线程应该永远不去访问固有资源,如文件、数据库,因为它会在任何时候甚至在一个操作的中间发生中断
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文件内容:
运行程序后 打开任务管理器 找到当前程序的PID
打开CMD 输入
jstack -l pid
可以看到快照结果
我们可以分析一下
C:\Users\heqianqian>jstack -l 100922017-04-15 09:54:03Full 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 conditionJNI global references: 236C:\Users\heqianqian>
可以看到是deamon线程 优先级是2 当前状态为有时间的等待状态
Locked ownable synchronizers 是否处于同步块中
最后显示的是我们的主线程
可以看到主线程并不是一个守护线程 并且处于等待状态 原因是我们的键盘输入阻塞了主线程
参考文章: