在Java中有两类线程:用户线程 (User Thread)、守护线程 (Daemon Thread)。
所谓守护 线程,是指在程序运行的时候在后台提供一种通用服务的线程,比如垃圾回收线程就是一个很称职的守护者,并且这种线程并不属于程序中不可或缺的部分。因 此,当所有的非守护线程结束时,程序也就终止了,同时会杀死进程中的所有守护线程。反过来说,只要任何非守护线程还在运行,程序就不会终止。
用户线程和守护线程两者几乎没有区别,唯一的不同之处就在于虚拟机的离开:如果用户线程已经全部退出运行了,只剩下守护线程存在了,虚拟机也就退出了。 因为没有了被守护者,守护线程也就没有工作可做了,也就没有继续运行程序的必要了。
将线程转换为守护线程可以通过调用Thread对象的setDaemon(true)方法来实现。在使用守护线程时需要注意一下几点:
(1) thread.setDaemon(true)必须在thread.start()之前设置,否则会跑出一个IllegalThreadStateException异常。你不能把正在运行的常规线程设置为守护线程。
(2) 在Daemon线程中产生的新线程也是Daemon的。
(3) 守护线程应该永远不去访问固有资源,如文件、数据库,因为它会在任何时候甚至在一个操作的中间发生中断。
代码示例:
package com.test; import java.util.concurrent.TimeUnit; /** * 守护线程 */ public class Daemons { /** * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { Thread d = new Thread(new Daemon()); d.setDaemon(true); //必须在启动线程前调用 d.start(); System.out.println("d.isDaemon() = " + d.isDaemon() + "."); TimeUnit.SECONDS.sleep(1); } } class DaemonSpawn implements Runnable { public void run() { while (true) { Thread.yield(); } } } class Daemon implements Runnable { private Thread[] t = new Thread[10]; public void run() { for (int i = 0; i < t.length; i++) { t[i] = new Thread(new DaemonSpawn()); t[i].start(); System.out.println("DaemonSpawn " + i + " started."); } for (int i = 0; i < t.length; i++) { System.out.println("t[" + i + "].isDaemon() = " + t[i].isDaemon() + "."); } while (true) { Thread.yield(); } } }
运行结果:
d.isDaemon() = true. DaemonSpawn 0 started. DaemonSpawn 1 started. DaemonSpawn 2 started. DaemonSpawn 3 started. DaemonSpawn 4 started. DaemonSpawn 5 started. DaemonSpawn 6 started. DaemonSpawn 7 started. DaemonSpawn 8 started. DaemonSpawn 9 started. t[0].isDaemon() = true. t[1].isDaemon() = true. t[2].isDaemon() = true. t[3].isDaemon() = true. t[4].isDaemon() = true. t[5].isDaemon() = true. t[6].isDaemon() = true. t[7].isDaemon() = true. t[8].isDaemon() = true. t[9].isDaemon() = true.
以上结果说明了守护线程中产生的新线程也是守护线程。
如果将mian函数中的TimeUnit.SECONDS.sleep(1);注释掉,运行结果如下:
d.isDaemon() = true. DaemonSpawn 0 started. DaemonSpawn 1 started. DaemonSpawn 2 started. DaemonSpawn 3 started. DaemonSpawn 4 started. DaemonSpawn 5 started. DaemonSpawn 6 started. DaemonSpawn 7 started. DaemonSpawn 8 started. DaemonSpawn 9 started.
以上结果说明了如果用户线程已经全部退出运行了,只剩下守护线程存在了,虚拟机也就退出了。下面的例子也说明了这个问题。
代码示例:
package com.test; import java.util.concurrent.TimeUnit; /** * Finally shoud be always run ? */ public class DaemonsDontRunFinally { /** * @param args */ public static void main(String[] args) { Thread t = new Thread(new ADaemon()); t.setDaemon(true); t.start(); } } class ADaemon implements Runnable { public void run() { try { System.out.println("start ADaemon..."); TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { System.out.println("Exiting via InterruptedException"); } finally { System.out.println("This shoud be always run ?"); } } }
运行结果:
start ADaemon...
如果将main函数中的t.setDaemon(true);注释掉,运行结果如下:
start ADaemon... This shoud be always run ?
相关推荐
守护线程(Daemon Thread)是一种特殊的线程,当所有非守护线程结束后,Java虚拟机会自动停止守护线程。例如,垃圾收集器就是守护线程。通过setDaemon(true)方法可以将线程设置为守护线程。 通过以上内容,你应该对...
Java并发编程中的线程基础是理解多线程编程的关键,它涵盖了从线程的创建到管理,再到线程间通信的全过程。多线程编程在处理高性能和高响应性的应用程序时至关重要,因为它允许程序在单个进程中同时执行多个任务,...
Java平台提供了丰富的并发工具和API,如线程(Thread)、守护线程(Daemon Thread)、线程池(ExecutorService)、锁(synchronized关键字和Lock接口)、并发集合(Concurrent Collections)等,这些都为开发者提供...
6. **线程池**:Executor框架是Java并发编程的重要组成部分,通过ThreadPoolExecutor可以创建线程池,有效管理和控制并发线程的数量,避免过度创建和销毁线程带来的性能开销。 7. **死锁、活锁与饥饿**:并发编程中...
2. **守护线程(Daemon Thread)**:后台运行的线程,当所有非守护线程结束时,程序会自动停止,常用于日志记录、垃圾收集等任务。 3. **线程通信**:`wait()`、`notify()`和`notifyAll()`方法用于线程间的协作,...
Java提供了多种并发工具,如线程(Thread)、守护线程(Daemon Thread)、线程池(ThreadPool)、Executor框架以及并发集合类等,帮助开发者构建并行应用程序。 1. **线程和线程安全**:Java中的线程是程序执行的...
在Java并发编程中,线程的关闭和取消是一项重要的任务,因为不正确的处理可能导致数据不一致、资源泄漏等问题。在Java中,强制停止线程并不是一个推荐的做法,因为这可能会导致系统状态的不稳定。传统的`Thread.stop...
Java提供了丰富的工具和API来支持并发编程,如线程(Thread)、守护线程(Daemon Thread)、线程池(Executor Service)等。 Java中的线程是并发的基础,通过创建Thread对象或实现Runnable接口可以创建新的线程。...
并发编程涉及到多个线程或进程同时执行任务,这在Java中通过Java线程API(java.lang.Thread)、并发工具类(java.util.concurrent)以及锁机制实现。以下是一些主要的知识点: 1. **线程的创建与启动**:Java中可以...
│ 高并发编程第一阶段12讲、Daemon线程的创建以及使用场景分析.mp4 │ 高并发编程第一阶段13讲、线程ID,优先级讲解.mp4 │ 高并发编程第一阶段14讲、Thread的join方法详细介绍,结合一个典型案例.mp4 │ 高...
同时,提到了守护线程(Daemon Thread)和线程优先级的概念。 第二章:共享数据与并发问题 在这一章中,作者深入讨论了多线程环境下共享数据带来的问题,如数据竞争(Race Condition)、死锁(Deadlock)、活锁...
此外,书中还介绍了守护线程(Daemon Thread)和用户线程的区别,以及如何设置和判断线程的优先级。 其次,线程池是Java并发编程中的重要工具。线程池可以有效地管理和复用线程,避免频繁创建和销毁线程带来的性能...
守护线程(daemon thread)是一种特殊的线程,它不会阻止Java虚拟机的退出,只有当所有非守护线程结束时,JVM才会退出。 Java提供了丰富的线程控制API,如`synchronized`关键字用于实现线程同步,防止数据竞争;`...
《Java并发编程:设计原则与模式(第二版)》是一本深入探讨Java平台上的多线程和并发编程的权威著作。这本书旨在帮助开发者理解和掌握如何有效地编写可扩展且高效的并发程序。以下是书中涵盖的一些关键知识点: 1....
Java通过`Thread`类实现了线程的创建和管理,同时JVM层面也提供了守护线程(Daemon Thread)的概念。 2. **同步机制**:Java提供了多种同步机制,包括`synchronized`关键字、`Lock`接口及其实现(如`ReentrantLock`...
在Java编程中,守护线程(Daemon Thread)是一种特殊的线程类型,它的主要特点是当所有非守护线程(用户线程)结束时,守护线程也会随之终止,即使守护线程本身仍在运行。守护线程通常被用作后台服务,如垃圾回收、...
2. **守护线程(Daemon Thread)**:不同于普通线程,守护线程不阻止程序的退出。Java 的 `Thread.setDaemon(true)` 方法可以将线程设置为守护线程。 3. **同步机制**:Java 提供了多种同步机制,包括 synchronized...
守护线程(Daemon Thread) 守护线程不会阻止JVM的退出,如后台的日志服务或垃圾回收线程。通过调用`setDaemon(true)`方法,可以将一个线程设置为守护线程。 总结,理解并熟练掌握Java并发编程是提升程序性能和...
在Java中,线程分为两种类型:用户线程(User Thread)和守护线程(Daemon Thread)。这两种线程在大部分行为上是相同的,但它们在决定虚拟机何时退出时有显著差异。 用户线程是程序的主要部分,Java虚拟机(JVM)...
### 并发编程基础知识,Java内存模型及多线程、volatile #### Java内存模型(JMM) Java内存模型(Java Memory Model, JMM)是Java并发编程的基础之一,它定义了一套规则来保证线程之间的数据可见性和一致性。当程序...