java多线程之守护线程和用户线程

        Java中的线程分为两类:守护线程和用户线程,守护线程被称为后台线程、用户线程被称为前台线程。守护线程一般被用来服务用户线程,两者之间的区别就是体现在JVM的运行上,当所有的用户线程结束,JVM会自动退出,这时候系统服务停止运行,守护线程自然也只能被迫停止。反之,守护线程全部结束不一定会导致JVM退出。

        守护线程和用户线程在使用上区别不大,守护线程只需要在使用时执行this.setDaemon(true)方法,且这个方法必须放在this.start()方法之前执行,否则会抛出IllegalThreadStateException异常,JDK源码中此方法上的注释也已经明确指出使用时的注意事项。

/**
     * Marks this thread as either a daemon thread or a user thread. The 
     * Java Virtual Machine exits when the only threads running are all 
     * daemon threads. 
     * <p>
     * This method must be called before the thread is started. 
      * <p>
     * This method first calls the <code>checkAccess</code> method 
     * of this thread 
     * with no arguments. This may result in throwing a 
     * <code>SecurityException </code>(in the current thread). 
    *
     * @param      on   if <code>true</code>, marks this thread as a
     *                  daemon thread.
     * @exception  IllegalThreadStateException  if this thread is active.
     * @exception  SecurityException  if the current thread cannot modify
     *               this thread.
     * @see        #isDaemon()
     * @see        #checkAccess
     */
    public final void setDaemon(boolean on) {
	checkAccess();
	if (isAlive()) {
	    throw new IllegalThreadStateException();
	}
	daemon = on;
    }

下面用一个例子来比较下守护线程和用户线程的执行情况:


package com.zw;

/**
 * 守护线程和用户线程
 * @author Administrator
 * 用户线程结束,JVM也就退出了,守护线程会立刻终止
 */
public class TestDaemon {

	public static void main(String[] args) {
		
		MyUserThread m = new MyUserThread();
		MyUserThread2 m2 = new MyUserThread2();
		MyDaemonThread md = new MyDaemonThread(m, m2);
		md.setDaemon(true); //设置md为守护线程
		md.start();
	}
}

/**
 * 守护线程
 * @author Administrator
 *
 */
class MyDaemonThread extends Thread {

	MyUserThread m = null;
	MyUserThread2 m2 = null;
	
	MyDaemonThread(MyUserThread m,MyUserThread2 m2) {
		this.m = m;
		this.m2 = m2;
		m.start();
		m2.start();
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		super.run();
		while(true) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("守护线程	      " + m.getI());
		}
	}
}

/**
 * 用户线程
 * @author Administrator
 *
 */
class MyUserThread extends Thread {
private int i = 0;
	
	public int getI()
	{
		return i;
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		super.run();
		while(i < 5) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("用户线程	      " + i++);
		}
	}
}

class MyUserThread2 extends Thread {
	private int i = 0;
	
	public int getI()
	{
		return i;
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		super.run();
		while(i < 10) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("用户线程2     " + i++);
		}
	}
}

执行结果:

用户线程          0
用户线程2     0
守护线程          1
用户线程          1
守护线程          2
用户线程2     1
用户线程          2
守护线程          3
用户线程2     2
用户线程          3
守护线程          4
用户线程2     3
用户线程          4
守护线程          5
用户线程2     4
守护线程          5
用户线程2     5
守护线程          5
用户线程2     6
守护线程          5
用户线程2     7
守护线程          5
用户线程2     8
守护线程          5
用户线程2     9

        上面的实例中启动了3个线程,一个守护线程md,两个用户线程m,m2。守护线程中无限循环执行输出,线程m执行结束时,守护线程还在自我循环中,但是当m2也结束时,守护线程也跟着停止了,这是因为m和m2两个用户线程全部结束,JVM检测到没有用户线程在执行,也就自动退出。JVM退出了,守护线程没了依托,也只能被迫停止。

        Java中的GC线程就是典型的守护线程,当系统停止了对象的创建,GC没有对象可回收,就会随着JVM退出而退出。


猜你喜欢

转载自blog.csdn.net/yewucainiao/article/details/75731397