Java线程_守护线程和用户线程

时间:2022-04-07 14:54:20

       用户线程是用户创建的一般线程,而守护线程则是为用户线程提供服务的。

       任何线程都可以是守护线程或者用户线程,所有线程一开始都是用户线程。守护线程和用户线程的区别在于,当一个用户线程结束后,Java虚拟机会检查系统中是否还存在其他用户线程,如果存在则按照正常的调用方法调用。但是如果只剩守护线程而没有用户线程的话,程序就会终止。Java中最典型的守护线程就是垃圾收集线程,垃圾收集线程负责回收程序中没用的内存空间。当程序中的其他用户线程终止以后,垃圾回收线程也就没有存在的意义了。

       涉及守护线程的方法有两个:setDaemon()和isDaemon()。需要注意的是:setDaemon()方法仅仅在线程对象已经被创建但是还没有运行前才能被调用,否则会报错。

       守护线程的使用:

package com.wly.javathread.chap6;

/**
 * 测试守护线程用法一
 * @author wly
 *
 */
public class TestDaemonThread1 {

	public static void main(String[] args) {
		MyUserThread userThread = new MyUserThread();
		MyDaemonThread daemonThread = new MyDaemonThread(userThread);
		userThread.start();
		daemonThread.start();
	}
	
	/**
	 * 守护线程
	 * @author wly
	 *
	 */
	static class MyDaemonThread extends Thread {
		private MyUserThread userThread;
		
		public MyDaemonThread(MyUserThread userThread) {
			this.userThread = userThread;
			//设置为守护线程
			setDaemon(true);
		}

		@Override
		public void run() {
			super.run();
			while(true) {
				try {
					sleep(700);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("--守护--:" + userThread.getI());
			}
		}
	}
	
	/**
	 * 用户线程
	 * @author wly
	 *
	 */
	static class MyUserThread extends Thread {
		int i = 0;

		public int getI() {
			return i;
		}
		
		@Override
		public void run() {
			super.run();
			
			while(i < 10) {
				System.out.println("--用户--:" + getI());
				i ++;
				try {
					sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

       运行结果:

--用户--:0
--用户--:1
--用户--:2
--用户--:3
--用户--:4
--用户--:5
--用户--:6
--守护--:7
--用户--:7
--用户--:8
--用户--:9

       从上面的运行结果可以看出,在所有用户线程运行完成后,程序将直接终止,以至于守护线程也会随着程序的终止而终止。

       有时守护线程中进行着某想关键性操作,必须保证操作的完整性。如:数据备份到数据库动作。此时需要守护线程与用户线程嵌套锁定来使用,或者说可以通过一个用户线程来保护守护线程。听上去可能有点别扭,用一个用户线程来保护一个守护线程?还是直接看代码吧:
        保护含关键性操作的守护线程:

package com.wly.javathread.chap6;

/**
 * 测试守护线程用法一
 * @author wly
 *
 */
public class TestDaemonThread2 {

	public static void main(String[] args) {

		MyUserThread userThread = new MyUserThread();
		userThread.start();
		
		MyDaemonThread daemonThread = new MyDaemonThread(userThread);
		daemonThread.start();
	}
	
	/**
	 * 守护线程
	 * @author wly
	 *
	 */
	static class MyDaemonThread extends Thread {
		
		private MyUserThread userThread;
		private MyLockThread lockThread;
		
		
		public MyDaemonThread(MyUserThread userThread) {
			setDaemon(true);
			this.userThread = userThread;

			lockThread = new MyLockThread();
			lockThread.start();
		}
		
		@Override
		public void run() {
			super.run();
			while(userThread.isAlive()) {
				try {
					sleep(700);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("--守护--:" + userThread.getI());
			}
			lockThread.releaseWiatThread();
		}
	}
	
	/**
	 * 自定义用户线程
	 * @author wly
	 *
	 */
	static class MyUserThread extends Thread {
		int i = 0;

		public int getI() {
			return i;
		}
		
		@Override
		public void run() {
			super.run();
			
			while(i < 10) {
				System.out.println("--用户--:" + getI());
				i ++;
				try {
					sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	/**
	 * 一个专门用于保护"守护线程"的线程类,重写了run()方法
	 * @author wly
	 *
	 */
	static class MyLockThread extends Thread {
		
		@Override
		public synchronized void run() {
			super.run();
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
		public synchronized void releaseWiatThread() {
			notify();
		}
	}
}

       运行结果:

--用户--:0
--用户--:1
--用户--:2
--用户--:3
--用户--:4
--用户--:5
--用户--:6
--用户--:7
--守护--:7
--用户--:8
--用户--:9
--守护--:10

       从上面运行结果可以看出,使用了一个临时的用户线程LockThread来保护守护线程,可以在负责计算的线程MyUserThread结束后,守护线程MyDaemonThread仍然完整的执行完了其打印任务。

      O啦~~~

      转载请保留出处:http://blog.csdn.net/u011638883/article/details/18447361
      谢谢!!