Java守护进程学习笔记
1.概述
Java的线程机制,在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程)。
Daemon的作用是为其他线程的运行提供服务,比如说GC线程。其实User Thread线程和Daemon Thread守护线程本质上来说去没啥区别的,唯一的区别之处就在虚拟机的离开时候:如果User Thread全部撤离,那么Daemon Thread也就没啥线程好服务的了,所以虚拟机也就退出了。只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作。守护线程最典型的应用就是 GC (垃圾回收器)。
1.1.注意点
public final void setDaemon(boolean on) ;但是有几点需要注意:
1)、thread.setDaemon(true)必须在thread.start()之前设置,否则会跑出一个IllegalThreadStateException异常。你不能把正在运行的常规线程设置为守护线程。 (备注:这点与守护进程有着明显的区别,守护进程是创建后,让进程摆脱原会话的控制+让进程摆脱原进程组的控制+让进程摆脱原控制终端的控制;所以说寄托于虚拟机的语言机制跟系统级语言有着本质上面的区别)
2)、 在Daemon线程中产生的新线程也是Daemon的。 (这一点又是与守护线程有着本质的区别了:
守护进程fork()出来的子进程不再是守护进程,尽管它把父进程的进程相关信息复制过去了,但是子进程的进程的父进程不是init进程,所谓的守护进程本质上说就是“父进程挂掉,init收养,然后文件0,1,2都是/dev/null,当前目录到/”)
3)、不是所有的应用都可以分配给Daemon线程来进行服务,比如读写操作或者计算逻辑。因为在Daemon Thread还没来的及进行操作时,虚拟机可能已经退出了。
1.2.应用场景
但是daemon Thread实际应用在那里呢?举个例子,web服务器中的Servlet,容器启动时后台初始化一个服务线程,即调度线程,负责处理http请求,然后每个请求过来调度线程从线程池中取出一个工作者线程来处理该请求,从而实现并发控制的目的。
2.实例
2.1.用户线程提前结束
没法守护了
2.1.1.代码
package com.tech.ability.resume;
import com.tech.ability.util.DateUtil;
import com.tech.ability.util.SleepUtil;
/**
- Created by kikop on 2019/6/11.
*/
public class DaemonTest {
/**
* 守护进程
*/
static class MyDamonRunner implements Runnable{
@Override
public void run() {
try{
System.out.println(DateUtil.getCurrentThreadInfo("begin..."));
SleepUtil.second(10);
} finally {
System.out.println(DateUtil.getCurrentThreadInfo("finally run!"));
}
}
}
/**
* 普通进程
*/
static class MyNormalRunner implements Runnable{
@Override
public void run() {
try{
System.out.println(DateUtil.getCurrentThreadInfo("begin..."));
SleepUtil.second(5);
} finally {
System.out.println(DateUtil.getCurrentThreadInfo("finally run!"));
}
}
}
/**
* main普通进程
* @param args
*/
public static void main(String[] args) {
Thread normalThread=new Thread(new MyNormalRunner(),"normalThread");
normalThread.start();
Thread daemonThread=new Thread(new MyDamonRunner(),"daemonThread");
daemonThread.setDaemon(true);
daemonThread.start();
}
}
2.1.2.输出结果
[2019-06-11 07:14:22] daemonThread-00012:begin...
[2019-06-11 07:14:22] normalThread-00011:begin...
[2019-06-11 07:14:27] normalThread-00011:finally run!
2.2.Daemon线程提前结束
2.2.1.代码
package com.tech.ability.resume;
import com.tech.ability.util.DateUtil;
import com.tech.ability.util.SleepUtil;
/**
- Created by kikop on 2019/6/11.
*/
public class DaemonTest {
/**
* 守护进程
*/
static class MyDamonRunner implements Runnable{
@Override
public void run() {
try{
System.out.println(DateUtil.getCurrentThreadInfo("begin..."));
SleepUtil.second(10); //守护线程阻塞
File f = new File("daemon.txt");
FileOutputStream os = new FileOutputStream(f, true);
os.write("daemon".getBytes());
} finally {
System.out.println(DateUtil.getCurrentThreadInfo("finally run!"));
}
}
}
/**
* 普通进程
*/
static class MyNormalRunner implements Runnable{
@Override
public void run() {
try{
System.out.println(DateUtil.getCurrentThreadInfo("begin..."));
SleepUtil.second(15);
} finally {
System.out.println(DateUtil.getCurrentThreadInfo("finally run!"));
}
}
}
/**
* main普通进程
* @param args
*/
public static void main(String[] args) {
Thread normalThread=new Thread(new MyNormalRunner(),"normalThread");
normalThread.start();
Thread daemonThread=new Thread(new MyDamonRunner(),"daemonThread");
daemonThread.setDaemon(true);
daemonThread.start();
}
}
2.2.2.输出结果
[2019-06-11 07:21:56] normalThread-00011:begin...
[2019-06-11 07:21:56] daemonThread-00012:begin...
[2019-06-11 07:22:07] daemonThread-00012:finally run!
[2019-06-11 07:22:12] normalThread-00011:finally run!
参考
1.java的守护进程与非守护进程
<u>https://blog.csdn.net/weixin_37766296/article/details/80404503</u>