在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程)
Daemon的作用是为其他线程的运行提供服务,比如说GC线程。其实User Thread线程和Daemon Thread守护线程本质上来说去没啥区别的,唯一的区别之处就在虚拟机的离开:如果User Thread全部撤离,那么Daemon Thread也就没啥线程好服务的了,所以虚拟机也就退出了。守护线程并非虚拟机内部可以提供,用户也可以自行的设定守护线程,方法:
| public final void setDaemon(boolean on); |
但是有几点需要注意:
1)、thread.setDaemon(true)必须在thread.start()之前设置,你不能把正在运行的常规线程设置为守护线程,否则会抛出一个IllegalThreadStateException异常。
2)、 在Daemon线程中产生的新线程也是Daemon的。
3)、不是所有的应用都适合分配给Daemon线程来进行服务,比如读写操作或者计算逻辑。因为在Daemon Thread还没来的及进行操作时,虚拟机可能已经退出了。The Java Virtual Machine exits when the only threads running are all daemon threads.JVM会在所有执行的线程都是守护线程的时候退出。
例子:
//完成文件输出的守护线程任务
import java.io.*;
class TestRunnable implements Runnable{
public void run(){
try{
Thread.sleep(1000);//守护线程阻塞1秒后运行
File f=new File("daemon.txt");
FileOutputStream os=new FileOutputStream(f,true);
os.write("daemon".getBytes());
}
catch(IOException e1){
e1.printStackTrace();
}
catch(InterruptedException e2){
e2.printStackTrace();
}
}
}
public class DaemonThreadDemo{
public static void main(String[] args) throws InterruptedException
{
Runnable tr=new TestRunnable();
Thread thread=new Thread(tr);
thread.setDaemon(true); //设置守护线程
thread.start(); //开始执行分进程
}
}运行结果:文件daemon.txt中没有"daemon"字符串。
但是如果把thread.setDaemon(true); //设置守护线程注释掉,文件daemon.txt是可以被写入daemon字符串的
JRE判断程序是否执行结束的标准是所有的前台执线程行完毕了,而不管后台线程的状态,因此,在使用后台线程候一定要注意这个问题。
Daemon线程的实际应用
以一个web服务器为例,通常有一个调度线程,用来接受用户的请求,然后将请求转发给工作线程来完成。这里工作线程是完成实际工作的,如果所有的工作线程都停止了,调度线程也就没有存在的必要了,因此,调度线程可以设置为守护线程。