2 minutes
Week1031_share
ARTS - Share 补2019.2.6
JVM的守护线程和用户线程
线程池创建非daemon线程
最近在看线程池时候, 发现线程池创建线程特别设置了线程为非daemon,以下是DefaultThreadFactory 中的一段代码:
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
于是就了解了下JVM的线程。
守护线程和用户线程
Java线程分类为daemon 即守护线程,和非守护线程即用户线程,守护线程一般用来辅助用户线程,如GC线程就是守护线程,
守护线程的生命周期:随着程序在JVM中运行,守护线程第一时间被启动,并且一直处于运行状态。
当所有用户线程执行完毕,程序就会杀死守护线程,离开JVM,终止程序。
也就是是说,当用户线程为0,那么JVM就会退出。
守护线程的创建
其实线程 Thread类里有个 setDaemon方法,用来设置线程为守护线程:
/**
* Marks this thread as either a {@linkplain #isDaemon daemon} thread
* or a user thread. The Java Virtual Machine exits when the only
* threads running are all daemon threads.
* 当所有运行的线程都是守护线程,那么JVM退出。
* <p> This method must be invoked before the thread is started.
注意这句,必须在start方法调用之前设置这个
*
* @param on
* if {@code true}, marks this thread as a daemon thread
*
* @throws IllegalThreadStateException
* if this thread is {@linkplain #isAlive alive}
*
* @throws SecurityException
* if {@link #checkAccess} determines that the current
* thread cannot modify this thread
*/
public final void setDaemon(boolean on) {
checkAccess();
if (isAlive()) {
throw new IllegalThreadStateException();
}
daemon = on;
}
另外守护线程创建的都是守护线程,当所有线程都为守护线程时候,JVM就会退出,下面我们验证一下:
import java.util.Scanner;
import java.util.concurrent.TimeUnit;
public class DaemonThreadTest extends Thread {
public static void main(String[] args) {
DaemonThreadTest test = new DaemonThreadTest();
test.setDaemon(true);
test.start();
Scanner sc = new Scanner(System.in);
sc.next();
Runtime.getRuntime().addShutdownHook(new Thread(() -> System.out.println("JVM exits!")));
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
TimeUnit.SECONDS.sleep(1);
Thread t = new Thread(() -> System.out.println("I am inner thread"));
System.out.println(" inner thread isDaemon = " + t.isDaemon());
t.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
以上逻辑很简单:
DaemonThreadTest 作为一个Daemon线程,它不停的创建线程,在主线程里加了个控制台输入的Scanner ,相当于用户线程,只要不输入,就不会退出,最后控制台打印的都是 daemon=true, 当手动输入字符回车之后,打印 JVM退出。
Read other posts