用户线程是用户创建的一般线程,而守护线程则是为用户线程提供服务的。
任何线程都可以是守护线程或者用户线程,所有线程一开始都是用户线程。守护线程和用户线程的区别在于,当一个用户线程结束后,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
谢谢!!