`

守护线程和Shutdown Hooks

阅读更多

线程分为两种:守护线程和用户线程(也叫非守护线程)。

 

可以通过ThreadsetDaemon(boolean on)方法将其设定为守护线程或用户线程。

setDaemon方法必须在线程启动前被调用。不然会产生IllegalThreadStateException异常。

并且,守护线程具有传递性,即如果一个线程是守护线程,那么它的子线程也会是守护线程。

 

守护线程是为了服务于用户线程而存在的,所以当Java的执行环境结束(调用System.exit方法停止JVM,或者所有非守护线程都结束时)守护线程也会退出。

 

有一点注意了,在application中要慎用用户线程,因为当JVM中存在alive的用户线程时,有可能会出现服务停止超时的情况。(当然,有些服务停止时会去调用System.exit方法,就不会有容器停止超时的情况出现)。

比如,GlassFish3.1.2JavaEE6Cluster停止的时候就不会去调用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并没有执行完成就退出了。

 

那是不是这个问题不能解决呢?当然不是,使用RuntimeaddShutdownHook(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并不是马上就退出,而是调用了addShutdownHooksleep10000ms后再退出。

 

0
2
分享到:
评论

相关推荐

    Java多线程编程线程的协同、停止、暂停、继续等操作实现

    线程池可以方便地管理和控制线程的创建、执行和销毁,包括停止所有线程的`shutdown()`和立即停止并取消所有任务的`shutdownNow()`方法。 6. **守护线程(Daemon Threads)** 守护线程是一种特殊类型的线程,它不会...

    Java多线程详解及示例

    守护线程(Daemon Thread)是一种特殊线程,当所有非守护线程结束时,守护线程也会随之结束,通常用于后台服务。 总结: Java多线程编程是提升程序性能和响应性的关键技术。理解多线程的概念,掌握线程的创建、同步...

    简单多线程实例简单多线程实例简单多线程实例

    - **守护线程**:守护线程(Daemon Thread)是一种特殊线程,当所有非守护线程结束时,守护线程也会自动结束。例如,Java虚拟机的垃圾收集器就是守护线程。 在实际开发中,多线程的运用十分广泛,例如在Web服务器...

    多线程安全退出实例源代码

    2. **使用守护线程(Daemon)**:Java中的守护线程在所有非守护线程结束后自动停止,这可以用来创建后台服务。但要注意,守护线程不应持有宝贵的系统资源,因为它们可能在没有清理资源的情况下突然停止。 3. **共享...

    ExecutorService.shutdown()应该是在线程执行完毕后,才会去关闭

    在Java多线程编程中,`ExecutorService`是线程池的一个重要接口,它提供了管理和控制线程执行的能力。当我们创建一个`ExecutorService`实例并提交任务时,我们可以通过调用`shutdown()`方法来关闭线程池。然而,标题...

    java线程和线程池的使用.docx

    - **守护线程(Daemon Thread)**:守护线程主要用于为其他线程提供服务,如垃圾回收器。当所有非守护线程(用户线程)结束时,守护线程也会随之结束。 - **用户线程(User Thread)**:用户线程是程序的主要工作...

    java面试第二部分:多线程与锁

    当所有非守护线程结束时,程序会退出,即使还有守护线程在运行。 **创建线程** Java提供三种创建线程的方法:继承Thread类并重写run()方法,实现Runnable接口,或实现Callable接口。Callable接口允许线程有返回值。...

    java 多线程实例

    守护线程是一种特殊的线程,它不会阻止JVM退出,即使还有守护线程在运行。通过调用`setDaemon(true)`方法可以将线程设置为守护线程。 7. 线程优先级: Java提供了线程优先级的概念,通过`setPriority()`方法可以...

    Oracle数据库startup和shutdown方式

    理解每种模式的含义和适用场景,能够帮助数据库管理员更加有效地管理数据库资源,确保数据的完整性和系统的稳定性。在执行任何操作前,建议备份关键数据,并根据实际情况选择最合适的操作模式。

    java 线程池源代码

    线程池的核心在于它能够有效地控制运行的线程数量,避免因为频繁创建和销毁线程而产生的性能开销。在Java中,`java.util.concurrent`包下的`ExecutorService`、`ThreadPoolExecutor`和`Executors`类是实现线程池的...

    java多线程,对多线程,线程池进行封装,方便使用

    Java多线程是Java编程中的重要概念,它允许程序同时执行多个任务,提高了程序的效率和响应速度。在Java中,我们可以通过实现Runnable接口或继承Thread类来创建线程。然而,直接使用线程可能存在一些问题,如资源管理...

    oracle 中shutdown命令的实用

    shutdown 命令可以按照方式分为三种:shutdown normal、shutdown immediate 和 shutdown abort。 1. shutdown normal shutdown normal 是关闭数据库的正常方式。该方式会等待所有活动会话完成后关闭数据库。在执行...

    java多线程

    6. **守护线程**:`setDaemon(true)`将线程标记为守护线程,当所有非守护线程结束时,即使还有守护线程在运行,JVM也会退出。 7. **死锁**:当两个或更多线程相互等待对方释放资源而无法继续执行时,就会发生死锁。...

    线程池管理多线程上传

    线程池管理和多线程上传是并发编程中的一个重要实践,特别是在大数据传输和网络服务中。在Java等编程语言中,线程池通过有效地管理和复用线程资源,避免了频繁创建和销毁线程带来的开销,提升了系统性能。下面将详细...

    一个JAVA多线程实例

    当所有非守护线程结束时,程序会退出,即使还有守护线程在运行。 8. 异常处理: 多线程环境下,每个线程都有自己的异常处理机制,通常需要在`run()`方法中使用`try-catch`结构来捕获和处理异常。 在提供的压缩包...

    java编程 线程的经典实用案例

    7. 守护线程(Daemon):守护线程主要用于为用户线程提供服务,如垃圾回收。当所有用户线程结束时,即使还有守护线程运行,JVM也会退出。 ```java Thread thread = new Thread(() -&gt; { // 守护线程代码 }); thread...

    深入浅出java多线程代码示例

    守护线程是一种特殊的线程,它的特点是当所有非守护线程结束时,守护线程也会自动结束。通常用于后台服务,如垃圾回收器。 以上只是Java多线程编程的基础知识,实际应用中还包括死锁检测、线程中断、线程安全的数据...

    21-多线程和线程同步1

    * ExecutorService 接口:提供了 execute() 方法、shutdown() 方法和 submit() 方法,用于执行 Runnable 任务和管理线程池。 * ThreadPoolExecutor 类:是一个线程池执行器,提供了一个固定大小的线程池。 Callable...

    Android开发经验谈:并发编程(线程与线程池)(推荐)

    我们需要了解线程和线程池的基本原理和应用场景,并掌握线程池的使用方法和参数设置,以便更好地使用线程池,提高应用程序的性能和响应速度。 知识点: * 线程和线程池的基本概念 * 线程池的类型和应用场景 * ...

    python多线程开发

    - 设置线程的`daemon`属性为`True`,当主线程结束时,守护线程也会被强制结束,无论其是否还在运行。 - 非守护线程则必须执行完毕才能结束进程。 7. **线程间的通信**: - 使用`queue`模块提供的队列类进行线程...

Global site tag (gtag.js) - Google Analytics