java里有一种特殊的线程叫做守护线程(Daemon)线程。这种线程的优先级很低,通常来说,当同一个应用程序里没有其他的线程运行的时候,守护线程才运行。当程序中唯一运行的的线程是守护线程时,并且守护线程执行结束后 ,JVM也就结束了这个程序。

因为这种特性,守护线程通常被用来作为同一程序中普通线程(用户线程)的服务提供者。它们通常是无线循环的,以等待服务请求或者执行线程的任务。它们不能做重要工作,因为我们不可能知道守护线程什么时候获取CPU时钟,并且,在没有其他线程运行时,守护线程随时可以结束。典型应用就是JAVA GC。

如何创建守护线程,写一个简单的DEMO。场景如下:有两线程,一种是用户线程,它将事件写到一个队列中。另一个是守护线程。他将管理这个队列。如果生成的事件超过10秒钟,就会被移除。

1.创建一个Event类。在类中声明两个私有属性,一个日期类型属性date;另一个字符串类型的属性event.并生成这两个属性的读写方法。

public class Event {
private Date date;
private String event;
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getEvent() {
return event;
}
public void setEvent(String event) {
this.event = event;
}

2.创建WriterTask类,用以实现Runnable接口。

public class WriterTask implements Runnable{}

3.声明一个存放Event对象的队列,并实现带参数的构造器,来初始化这个队列对象。

Deque deque;
public WriterTask(Deque deque) {
this.deque = deque;
}

4.实现线程的run()方法。它将执行100次循环。在每次循环中,都会创建一个新的Event对象,并放入队列中。然后休眠一秒钟。

public void run(){
for (int i=0;i<100;i++){
Event event=new Event();
event.setDate(new Date());
event.setEvent(String.format("The thread %s has generated an event", Thread.currentThread().getId()));
deque.addFirst(event);
try{
TimeUnit.SECONDS.sleep(1);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}

5.创建CleanerTask类并继承Thrad类。

public class CleanerTask extends Thread{}

6.声明存放Event对象的队列,并实现构造器,来初始化这个队列对象。同时,在这个构造器中,通过setDaemon()方法把这个线程设置为守护线程。

Deque deque;
public CleanerTask(Deque deque) {
this.deque = deque;
setDaemon(true);
}

7.实现run()方法,它会无限制的重复运行,在每次运行中,将获取当前的时间,并调用clean()方法。

public void run(){
while(true){
Date date=new Date();
clean(date);
}
}

8.实现clean()方法。clean()方法将读取队列的最后一个事件对象,如果这个事件是10秒种前创建的,就将它删除并且检查下一个。如果有事件被删除,clean()讲打印被删除事件信息,讲打印队列长度。

public void clean(Date date){
long diffrence;
boolean delete;
if(deque.size()==0){
return;
}
delete=false;
do{
Event e=deque.getLast();
diffrence=date.getTime()-e.getDate().getTime();
if(diffrence>10000){
System.out.printf("Cleaner:%s\n",e.getEvent());
deque.removeLast();
delete=true;
}
}while(diffrence>10000);
if(delete){
System.out.printf("Cleaner: Size of the queue: %d\n",deque.size());
}
}public void clean(Date date){
long diffrence;
boolean delete;
if(deque.size()==0){
return;
}
delete=false;
do{
Event e=deque.getLast();
diffrence=date.getTime()-e.getDate().getTime();
if(diffrence>10000){
System.out.printf("Cleaner:%s\n",e.getEvent());
deque.removeLast();
delete=true;
}
}while(diffrence>10000);
if(delete){
System.out.printf("Cleaner: Size of the queue: %d\n",deque.size());
}

9.创建一个包含main()方法的Main主类。

public class Main {
public static void main(String[] args) {}}

10.创建一个队列对象Deque,用来存放事件。

Deque deque=new ArrayDeque();

11.创建三个WriterTask线程和一个CleanerTask线程,并启动。

WriterTask writer=new WriterTask(deque);
for(int i=0;i<3;i++){
Thread thread=new Thread(writer);
thread.start();
}
CleanerTask cleaner=new CleanerTask(deque);
cleaner.start();
}
}

12.运行,查看结果。发现,队列对象会不断增长到30个,然后到程序结束,队列长度维持在27-30之间,