您的位置:首页 > 编程语言 > Java开发

Java并发编程初级篇(六):守护线程

2016-11-23 00:00 232 查看
摘要: 在Java中存在一种优先级很低的线程叫做守护线程。

Java中的提供的守护线程优先级很低。也就是说,当同一个应用中中没有其他线程运行的时候,守护线程才运行,当其他线程都已经终止后,守护线程成为了唯一的运行线程时,那么守护线程就会终止,JVM应用结束。

因为守护线程的特性,通常情况下守护线程是用来为普通线程提供服务的。它在结构设计上是无限循环的,并且不能够承担重要工作,因为我们不知道守护线程什么时候能够获取CPU时间,守护线程也不能够独立存在。在Java中,守护线程最典型的一个例子就是垃圾收集器(GC)。

在Java API中提供了Thread.setDaemon(true)方法把一个线程设置成守护线程。

下面我们来实现一个守护线程的例子,在这里例子中我们模拟一个生产者不断地向Deque中生产Event对象,然后模拟一个守护进程,它的作用就是检查Deque来保证Deque中的Event生产时间都是10秒内的。

首先我们定义一个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;
}
}

下面我们定义一个生产者线程,用来不断地向Deque中生产Event对象,并记录生产时间。

public class ProducerTask implements Runnable {
private Deque<Event> deque;

public ProducerTask(Deque<Event> deque) {
this.deque = deque;
}

@Override
public void run() {
for (int i = 0; i < 100; i++) {
Event event = new Event();
event.setDate(new Date());
event.setEvent(Thread.currentThread().getName() + " Event:" + i);
deque.addFirst(event);

System.out.printf("%s: Produce one event %s.\n", Thread.currentThread().getName(), event.getEvent());

try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

定义守护线程,保证Deque中生产的Event对象都是10秒内的。

public class GuardTask implements Runnable {
private Deque<Event> deque;

public GuardTask(Deque<Event> deque) {
this.deque = deque;
}

@Override
public void run() {
while (true) {
Event event = deque.getLast();

Date now = new Date();

if (now.getTime() - event.getDate().getTime() > 10000) {
deque.removeLast();

System.out.printf("%s: Clean Deque %s. Deque size is %d.\n",
Thread.currentThread().getName(),
event.getEvent(),
deque.size());
}
}
}
}

定义主方法类,启动三个生产者线程,并注册一个守护线程。

public class Main {
public static void main(String[] args) {
Deque<Event> deque = new ArrayDeque<Event>();

Thread producer1 = new Thread(new ProducerTask(deque), "Producer-1");
Thread producer2 = new Thread(new ProducerTask(deque), "Producer-2");
Thread producer3 = new Thread(new ProducerTask(deque), "Producer-3");

producer1.start();
producer2.start();
producer3.start();

//创建守护线程
Thread guard = new Thread(new GuardTask(deque), "Guard");
guard.setDaemon(true);

guard.start();
}
}

查看日志,我们会发现因为守护线程的存在,保证了Deque中的Event数量稳定在了27-30个,最后当所有线程都结束后,守护线程也就结束了。

Producer-3: Produce one event Producer-3 Event:98.
Producer-2: Produce one event Producer-2 Event:98.
Producer-1: Produce one event Producer-1 Event:98.
Guard: Clean Deque Producer-3 Event:89. Deque size is 24.
Guard: Clean Deque Producer-2 Event:89. Deque size is 23.
Guard: Clean Deque Producer-1 Event:89. Deque size is 22.
Producer-3: Produce one event Producer-3 Event:99.
Producer-2: Produce one event Producer-2 Event:99.
Producer-1: Produce one event Producer-1 Event:99.
Guard: Clean Deque Producer-3 Event:90. Deque size is 24.
Guard: Clean Deque Producer-1 Event:90. Deque size is 23.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息