线程分为两种:守护线程和用户线程(也叫非守护线程)。
可以通过Thread的setDaemon(boolean on)方法将其设定为守护线程或用户线程。
setDaemon方法必须在线程启动前被调用。不然会产生IllegalThreadStateException异常。
并且,守护线程具有传递性,即如果一个线程是守护线程,那么它的子线程也会是守护线程。
守护线程是为了服务于用户线程而存在的,所以当Java的执行环境结束(调用System.exit方法停止JVM时,或者所有非守护线程都结束时)守护线程也会退出。
有一点注意了,在application中要慎用用户线程,因为当JVM中存在alive的用户线程时,有可能会出现服务停止超时的情况。(当然,有些服务停止时会去调用System.exit方法,就不会有容器停止超时的情况出现)。
比如,GlassFish3.1.2的JavaEE6的Cluster停止的时候就不会去调用System.exit方法。
但是,守护线程也不是使用与所有的情况下的。比如:读写操作或者逻辑计算
我们看下面的一个例子
public class DaemonThread extends Thread { public void run() { for (int i = 0; i < 999; i++) { System.out.println("This is Daemon Thread:" + i); try { Thread.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class UserThread extends Thread { public void run() { for (int i = 0; i < 5; i++) { System.out.println("This is User Thread:" + i); try { Thread.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class HookTest { public static void main(String[] args) { Thread t1 = new DaemonThread(); Thread t2 = new UserThread(); t1.setDaemon(true); t1.start(); t2.start(); } }
此时,console中输出如下:
This is Daemon Thread:0 This is User Thread:0 This is User Thread:1 This is Daemon Thread:1 This is User Thread:2 This is Daemon Thread:2 This is User Thread:3 This is Daemon Thread:3 This is User Thread:4 This is Daemon Thread:4 This is Daemon Thread:5
可以看到:程序只保证了User Thread的执行,Daemon Thread并没有执行完成就退出了。
那是不是这个问题不能解决呢?当然不是,使用Runtime的addShutdownHook(Thread hook)方法就可以!
addShutdownHook方法会在JVM停止前被调用,也就是说,JVM会等addShutdownHook中的Thread执行结束后才关闭。这样,就可以等用户的操作都结束后,才退出JVM。
上面的那个例子,Main函数就可以改写为以下的样子:
public static void main(String[] args){ Runtime.getRuntime().addShutdownHook( new Thread(){ public void run(){ System.out.println("This is Shutdown Hook!!!"); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } } ); Thread t1 = new DaemonThread(); Thread t2 = new UserThread(); t1.setDaemon(true);//设置为守护程序 t1.start(); t2.start(); }
此时,consloe中输出如下:
This is Daemon Thread:0 This is User Thread:0 This is User Thread:1 This is Daemon Thread:1 This is User Thread:2 This is Daemon Thread:2 This is User Thread:3 This is Daemon Thread:3 This is User Thread:4 This is Daemon Thread:4 This is Daemon Thread:5 This is Shutdown Hook!!! This is Daemon Thread:6 …… This is Daemon Thread:996 This is Daemon Thread:997 This is Daemon Thread:998
可以看到:User Thread执行结束后,JVM并不是马上就退出,而是调用了addShutdownHook,sleep了10000ms后再退出。
相关推荐
线程池可以方便地管理和控制线程的创建、执行和销毁,包括停止所有线程的`shutdown()`和立即停止并取消所有任务的`shutdownNow()`方法。 6. **守护线程(Daemon Threads)** 守护线程是一种特殊类型的线程,它不会...
守护线程(Daemon Thread)是一种特殊线程,当所有非守护线程结束时,守护线程也会随之结束,通常用于后台服务。 总结: Java多线程编程是提升程序性能和响应性的关键技术。理解多线程的概念,掌握线程的创建、同步...
- **守护线程**:守护线程(Daemon Thread)是一种特殊线程,当所有非守护线程结束时,守护线程也会自动结束。例如,Java虚拟机的垃圾收集器就是守护线程。 在实际开发中,多线程的运用十分广泛,例如在Web服务器...
2. **使用守护线程(Daemon)**:Java中的守护线程在所有非守护线程结束后自动停止,这可以用来创建后台服务。但要注意,守护线程不应持有宝贵的系统资源,因为它们可能在没有清理资源的情况下突然停止。 3. **共享...
在Java多线程编程中,`ExecutorService`是线程池的一个重要接口,它提供了管理和控制线程执行的能力。当我们创建一个`ExecutorService`实例并提交任务时,我们可以通过调用`shutdown()`方法来关闭线程池。然而,标题...
- **守护线程(Daemon Thread)**:守护线程主要用于为其他线程提供服务,如垃圾回收器。当所有非守护线程(用户线程)结束时,守护线程也会随之结束。 - **用户线程(User Thread)**:用户线程是程序的主要工作...
当所有非守护线程结束时,程序会退出,即使还有守护线程在运行。 **创建线程** Java提供三种创建线程的方法:继承Thread类并重写run()方法,实现Runnable接口,或实现Callable接口。Callable接口允许线程有返回值。...
守护线程是一种特殊的线程,它不会阻止JVM退出,即使还有守护线程在运行。通过调用`setDaemon(true)`方法可以将线程设置为守护线程。 7. 线程优先级: Java提供了线程优先级的概念,通过`setPriority()`方法可以...
理解每种模式的含义和适用场景,能够帮助数据库管理员更加有效地管理数据库资源,确保数据的完整性和系统的稳定性。在执行任何操作前,建议备份关键数据,并根据实际情况选择最合适的操作模式。
线程池的核心在于它能够有效地控制运行的线程数量,避免因为频繁创建和销毁线程而产生的性能开销。在Java中,`java.util.concurrent`包下的`ExecutorService`、`ThreadPoolExecutor`和`Executors`类是实现线程池的...
shutdown 命令可以按照方式分为三种:shutdown normal、shutdown immediate 和 shutdown abort。 1. shutdown normal shutdown normal 是关闭数据库的正常方式。该方式会等待所有活动会话完成后关闭数据库。在执行...
6. **守护线程**:`setDaemon(true)`将线程标记为守护线程,当所有非守护线程结束时,即使还有守护线程在运行,JVM也会退出。 7. **死锁**:当两个或更多线程相互等待对方释放资源而无法继续执行时,就会发生死锁。...
线程池管理和多线程上传是并发编程中的一个重要实践,特别是在大数据传输和网络服务中。在Java等编程语言中,线程池通过有效地管理和复用线程资源,避免了频繁创建和销毁线程带来的开销,提升了系统性能。下面将详细...
当所有非守护线程结束时,程序会退出,即使还有守护线程在运行。 8. 异常处理: 多线程环境下,每个线程都有自己的异常处理机制,通常需要在`run()`方法中使用`try-catch`结构来捕获和处理异常。 在提供的压缩包...
Java多线程是Java编程中的重要概念,它允许程序同时执行多个任务,提高了程序的效率和响应速度。在Java中,我们可以通过实现Runnable接口或继承Thread类来创建线程。然而,直接使用线程可能存在一些问题,如资源管理...
7. 守护线程(Daemon):守护线程主要用于为用户线程提供服务,如垃圾回收。当所有用户线程结束时,即使还有守护线程运行,JVM也会退出。 ```java Thread thread = new Thread(() -> { // 守护线程代码 }); thread...
守护线程是一种特殊的线程,它的特点是当所有非守护线程结束时,守护线程也会自动结束。通常用于后台服务,如垃圾回收器。 以上只是Java多线程编程的基础知识,实际应用中还包括死锁检测、线程中断、线程安全的数据...
* ExecutorService 接口:提供了 execute() 方法、shutdown() 方法和 submit() 方法,用于执行 Runnable 任务和管理线程池。 * ThreadPoolExecutor 类:是一个线程池执行器,提供了一个固定大小的线程池。 Callable...
我们需要了解线程和线程池的基本原理和应用场景,并掌握线程池的使用方法和参数设置,以便更好地使用线程池,提高应用程序的性能和响应速度。 知识点: * 线程和线程池的基本概念 * 线程池的类型和应用场景 * ...
- 设置线程的`daemon`属性为`True`,当主线程结束时,守护线程也会被强制结束,无论其是否还在运行。 - 非守护线程则必须执行完毕才能结束进程。 7. **线程间的通信**: - 使用`queue`模块提供的队列类进行线程...