创建守护线程(deamon thread)
Java中有一种线程叫做守护线程(deamon thread),这类线程一般优先级都是最低的,守护线程一般作为后台服务来运行,或者用来调用用户线程;守护线程一般不做重要的工作,因为我们不知道他们什么时候占用cpu time,也不知道他们什么时候结束;一个典型的例子是java garbage collector;
下面的例子中创建一个线程和一个deamon线程,线程写事件到一个队列中,守护线程清除队列中10秒之前的事件;如果写事件线程全部结束后,通知守护线程终止;
动手实现
(1)创建Event类,记录事件名称和开始时间,有两个属性 String name, Date date;
(2)创建写事件线程
public class WriterTask implements Runnable {
private Deque<Event> deque;
public WriterTask(Deque<Event> deque) {
this.deque = deque;
}
@Override
public void run() {
System.out.println("WriterTask start");
for (int i = 0; i < 10; i++) {
Event event=new Event();
event.setDate(new Date());
event.setEvent("Event_" + Thread.currentThread().getId());
deque.addFirst(event);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("WriterTask done");
}
}
(3)创建清理事件守护线程
public class CleanerTask extends Thread {
private Deque<Event> deque;
public CleanerTask(Deque<Event> deque) {
this.deque = deque;
}
@Override
public void run() {
System.out.println("clean start.");
Date date=new Date();
boolean flag=true;
while (flag) {
if(deque.size()==0) continue;
Event e=deque.getLast();
if((date.getTime()-e.getDate().getTime())>10000){
System.out.printf("Cleaner:%s\n", e.getEvent());
deque.removeLast();
System.out.printf("Cleaner: Size of the queue: %d\n",deque.size());
}
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e1) {
flag=false;
}
}
System.out.println("clean end");
}
}
(4)Main
public class Main {
public static void main(String[] args) {
Deque<Event> deque=new ArrayDeque<>();
WriterTask writer=new WriterTask(deque);
Thread thread[]=new Thread[3];
for (int i=0; i<3; i++){
thread[i]=new Thread(writer);
thread[i].start();
}
CleanerTask cleaner=new CleanerTask(deque);
cleaner.start();
//等待写线程结束,然后结束清理线程,否则清理线程将无限循环
for (Thread aThread : thread) {
try {
aThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//当生产者结束后,通知消费则终止
cleaner.interrupt();
}
}
一次运行结果:
WriterTask start
WriterTask start
WriterTask start
clean start.
WriterTask done
WriterTask done
WriterTask done
clean end
要点
将一个线程设置为守护线程,在调用start()方法之前,调用Thread类的setDaemon()方法,一旦线程运行后就不能够修改deamon状态了;可以使用isDeamon()方法检查一个线程是否是守护线程