一、概述
当一个应用程序里没有其他的线程运行的时候,守护线程才运行;当守护线程是程序中唯一运行的线程时,守护线程执行结束后,JVM也就结束了这个程序。
基于以上特性,守护线程通常被用来作为同一程序中普通线程(也称之为用户线程)的服务提供者。它们通常是无限循环的,以等待服务请求或者执行线程的任务。它们不能做重要的工作,因为不可能知道守护线程什么时候能够获取 cpu 时钟,并且,在没有其他线程运行的时候,守护线程随时可能结束。典型的守护线程 Java 的垃圾回收器。
注意:
1、setDaemon() 方法只能在 start() 方法被调用之前设置;一旦线程开始运行,将不能再修改守护状态;
2、isDaemon() 方法被用来检查一个线程是否是守护线程,返回 true 表示守护线程,false 表示 这个线程是 用户线程;
二、实现
示例: 创建2个线程:一个是用户线程,它将事件写入到一个队列中;另外一个是守护线程,它将管理这个队列,如果生成的事件超过 10 秒钟,该事件就会被删除。
import java.util.Date;
/**
* 自定义事件
*/
public class MyEvent {
public static int globalI = 0;
public int id;
private String name;
private Date createTime;
public MyEvent(){
modifyI();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public String toString() {
return "MyEvent [id=" + id + ", name=" + name + ", createTime="
+ createTime + "]";
}
// 创建唯一编号的事件.
public synchronized void modifyI(){
id = ++globalI;
setId(id);
}
}
import java.util.Date;
import java.util.Queue;
import java.util.concurrent.TimeUnit;
/**
* 向队列中放入待处理的事件
*/
public class WriterTask implements Runnable{
private Queue<MyEvent> queue;
public WriterTask(Queue<MyEvent> queue){
this.queue = queue;
}
public void run() {
if(queue == null){
System.out.println("添加操作-存放的 queue队列 未能初始化...");
}
for(int i=0;i<3;i++){
MyEvent myEvent = new MyEvent();
myEvent.setName("name_" +i);
myEvent.setCreateTime(new Date());
queue.add(myEvent);
System.out.println(Thread.currentThread().getName() + "添加一个待处理事件:" + myEvent);
try {
TimeUnit.SECONDS.sleep(1); //休眠1s
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":现有 queue中的事件数为:" + queue.size());
}
}
}
import java.util.Date;
import java.util.Queue;
import java.util.concurrent.TimeUnit;
/***
* 清理 queue 队列中的 待处理事件.
*/
public class CleanTesk extends Thread{
private Queue<MyEvent> queue;
public CleanTesk(Queue<MyEvent> queue){
this.queue = queue;
setDaemon(true); // 设置为 守护线程 - 此方法是 Thread类中的
}
public void run() {
if (queue == null) {
System.out.println("清理操作-存放的 queue队列 未能初始化...");
}
while(true){
Date date = new Date();
clean(date);
}
}
// 清理操作
public void clean(Date date){
boolean isDelete = false;
if(queue.size() == 0){
System.out.println("清理操作-存放的 queue队列 没有待处理的事件...");
try {
TimeUnit.SECONDS.sleep(10); //10s
} catch (InterruptedException e) {
e.printStackTrace();
}
return;
}
MyEvent myEvent = queue.poll();
if(myEvent == null){
System.out.println("清理操作-获取待处理的事件无效...");
return;
}
long difference = date.getTime() - myEvent.getCreateTime().getTime();
if(difference >= 10000){ // 10s
isDelete = true;
}else{ // 时间不够,再放回去
queue.add(myEvent);
}
if(isDelete){
System.out.println(Thread.currentThread().getName()+"-清理了 一个待处理任务...myevent:"+myEvent);
try {
TimeUnit.SECONDS.sleep(1); //休息1s
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"-还剩的待处理任务...queue:"+queue.size());
}
}
}
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* 守护线程测试
*/
public class DaemonTest {
public static void main(String[] args) {
Queue<MyEvent> queue = new LinkedBlockingQueue<MyEvent>();
WriterTask writerTask = new WriterTask(queue);
for(int i=0;i<3;i++){
Thread thread = new Thread(writerTask);
thread.start();
}
CleanTesk cleanTesk = new CleanTesk(queue);
Thread clearThread = new Thread(cleanTesk);
clearThread.start();
}
}
//console打印结果:
清理操作-存放的 queue队列 没有待处理的事件...
Thread-1添加一个待处理事件:MyEvent [id=1, name=name_0, createTime=Tue Sep 05 16:02:01 CST 2017]
Thread-0添加一个待处理事件:MyEvent [id=2, name=name_0, createTime=Tue Sep 05 16:02:01 CST 2017]
Thread-2添加一个待处理事件:MyEvent [id=3, name=name_0, createTime=Tue Sep 05 16:02:01 CST 2017]
Thread-0:现有 queue中的事件数为:3
Thread-2:现有 queue中的事件数为:3
Thread-0添加一个待处理事件:MyEvent [id=4, name=name_1, createTime=Tue Sep 05 16:02:02 CST 2017]
Thread-1:现有 queue中的事件数为:3
Thread-2添加一个待处理事件:MyEvent [id=5, name=name_1, createTime=Tue Sep 05 16:02:02 CST 2017]
Thread-1添加一个待处理事件:MyEvent [id=6, name=name_1, createTime=Tue Sep 05 16:02:02 CST 2017]
Thread-0:现有 queue中的事件数为:6
Thread-2:现有 queue中的事件数为:6
Thread-0添加一个待处理事件:MyEvent [id=7, name=name_2, createTime=Tue Sep 05 16:02:03 CST 2017]
Thread-2添加一个待处理事件:MyEvent [id=8, name=name_2, createTime=Tue Sep 05 16:02:03 CST 2017]
Thread-1:现有 queue中的事件数为:8
Thread-1添加一个待处理事件:MyEvent [id=9, name=name_2, createTime=Tue Sep 05 16:02:03 CST 2017]
Thread-0:现有 queue中的事件数为:9
Thread-1:现有 queue中的事件数为:9
Thread-2:现有 queue中的事件数为:9
Thread-4-清理了 一个待处理任务...myevent:MyEvent [id=1, name=name_0, createTime=Tue Sep 05 16:02:01 CST 2017]
Thread-4-还剩的待处理任务...queue:8
Thread-4-清理了 一个待处理任务...myevent:MyEvent [id=2, name=name_0, createTime=Tue Sep 05 16:02:01 CST 2017]
Thread-4-还剩的待处理任务...queue:7
Thread-4-清理了 一个待处理任务...myevent:MyEvent [id=3, name=name_0, createTime=Tue Sep 05 16:02:01 CST 2017]
Thread-4-还剩的待处理任务...queue:6
Thread-4-清理了 一个待处理任务...myevent:MyEvent [id=4, name=name_1, createTime=Tue Sep 05 16:02:02 CST 2017]
Thread-4-还剩的待处理任务...queue:5
Thread-4-清理了 一个待处理任务...myevent:MyEvent [id=5, name=name_1, createTime=Tue Sep 05 16:02:02 CST 2017]
Thread-4-还剩的待处理任务...queue:4
Thread-4-清理了 一个待处理任务...myevent:MyEvent [id=6, name=name_1, createTime=Tue Sep 05 16:02:02 CST 2017]
Thread-4-还剩的待处理任务...queue:3
Thread-4-清理了 一个待处理任务...myevent:MyEvent [id=7, name=name_2, createTime=Tue Sep 05 16:02:03 CST 2017]
Thread-4-还剩的待处理任务...queue:2
Thread-4-清理了 一个待处理任务...myevent:MyEvent [id=8, name=name_2, createTime=Tue Sep 05 16:02:03 CST 2017]
Thread-4-还剩的待处理任务...queue:1
Thread-4-清理了 一个待处理任务...myevent:MyEvent [id=9, name=name_2, createTime=Tue Sep 05 16:02:03 CST 2017]
Thread-4-还剩的待处理任务...queue:0
清理操作-存放的 queue队列 没有待处理的事件...