2.9 守护线程
在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服务器为例,通常有一个调度线程
,用来接受用户的请求,然后将请求转发给工作线程
来完成。这里工作线程是完成实际工作的,如果所有的工作线程都停止了,调度线程也就没有存在的必要了,因此,调度线程可以设置为守护线程。