Java线程类型有两种,分别是用户线程(User Thread) 和 守护线程(Daemon Thread)。
举个场景,比如我们在编写文档,有线程在处理输入,有线程在后台默默替我们检查语法;处理输入的是用户线程,检查语法的是守护线程。当我们退出文档,即所有的用户线程都结束了,守护线程也会随之退出。常见的守护线程比如垃圾回收线程。
过thread.setDaemon(true),就可以把一个线程指定为守护线程,这是两种线程在编码中唯一的区别。
守护线程时有几个注意事项:
setDaemon(true)必须在 start()之前执行,否则抛出IllegalThreadStateException。
2. 不能把一个正在运行的正常线程设置为守护线程。
Daemon Thread 产生的新线程也是Daemon Thread。
4.User Thread全部结束后,Daemon Thread会退出,不管Daemon Thread中是否正在执行任务。因此,我们需要小心,不要认为所有的任务都可以分配给Daemon Thread。
为了更好的认识Daemon Thread,我们来做个示例。一共有两个类,分别名为UserThread.java和DaemonThread.java,演示过程如下。
UserThread中把DaemonThread设置成守护线程,并启动守护线程,然后用键盘输入把当前的用户线程阻塞。
DaemonThread.java每隔10s打印一个数字,观察控制台。
3. 控制台输出若干数字后,在控制台输入任意字符,并回车,发现两个线程都退出了。
DaemonThread.java
/**
* 通过Thread.setDaemon(true)把一个线程设置为守护线程
*
*setDaemon(true)必须在Thread.start()之前执行
*
*当用户进程执行完毕,守护线程就会死亡。假如此时守护线程正在执行操作,那么也会中断。
*/
public class DaemonThread implements Runnable {
public void run() {
System.out.println("进入守护线程:\t" + Thread.currentThread().getName());
printNumer();
//这句话有可能是不会被执行
System.out.println("退出守护线程:\t" + Thread.currentThread().getName());
}
private void printNumer() {
int count = 0;
try {
while (count < 100) {
System.out.println(count);
count++;
Thread.sleep(10000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 通过Thread.setDaemon(true)把一个线程设置为守护线程
*
*setDaemon(true)必须在Thread.start()之前执行
*
*当用户进程执行完毕,守护线程就会死亡。假如此时守护线程正在执行操作,那么也会中断。
*/
public class DaemonThread implements Runnable {
public void run() {
System.out.println("进入守护线程:\t" + Thread.currentThread().getName());
printNumer();
//这句话有可能是不会被执行
System.out.println("退出守护线程:\t" + Thread.currentThread().getName());
}
private void printNumer() {
int count = 0;
try {
while (count < 100) {
System.out.println(count);
count++;
Thread.sleep(10000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
UserThread.java
public class UserThread {
public static void main(String[] args) {
System.out.println("进入用户线程(主线程)," + Thread.currentThread().getName());
DaemonThread dt = new DaemonThread();
Thread t = new Thread(dt,"DaemonThread");
t.setDaemon(true);// 设置为守护线程,必须在start之前
t.start();
//用键盘输入来阻塞当前的用户线程,先让守护运行执行一会儿,再输入字符,回车,看效果
Scanner scan = new Scanner(System.in);
scan.next();
scan.close();
System.out.println("退出用户线程(主线程)," + Thread.currentThread().getName());
}
}
public class UserThread {
public static void main(String[] args) {
System.out.println("进入用户线程(主线程)," + Thread.currentThread().getName());
DaemonThread dt = new DaemonThread();
Thread t = new Thread(dt,"DaemonThread");
t.setDaemon(true);// 设置为守护线程,必须在start之前
t.start();
//用键盘输入来阻塞当前的用户线程,先让守护运行执行一会儿,再输入字符,回车,看效果
Scanner scan = new Scanner(System.in);
scan.next();
scan.close();
System.out.println("退出用户线程(主线程)," + Thread.currentThread().getName());
}
}