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